Skip to content

Commit d84c482

Browse files
committed
bpo-37483: add _PyObject_CallOneArg() function
1 parent d4efd91 commit d84c482

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+128
-146
lines changed

Doc/c-api/object.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,17 @@ Object Protocol
264264
.. versionadded:: 3.9
265265
266266
267+
.. c:function:: PyObject* _PyObject_CallOneArg(PyObject *callable, PyObject *arg)
268+
269+
Call a callable Python object *callable* with exactly 1 positional argument
270+
*arg* and no keyword arguments.
271+
272+
Return the result of the call on success, or raise an exception and return
273+
*NULL* on failure.
274+
275+
.. versionadded:: 3.9
276+
277+
267278
.. c:function:: PyObject* PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
268279
269280
Call a callable Python object *callable*, with arguments given by the

Include/cpython/abstract.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ PyVectorcall_NARGS(size_t n)
6262
static inline vectorcallfunc
6363
_PyVectorcall_Function(PyObject *callable)
6464
{
65+
assert(callable != NULL);
6566
PyTypeObject *tp = Py_TYPE(callable);
6667
if (!PyType_HasFeature(tp, _Py_TPFLAGS_HAVE_VECTORCALL)) {
6768
return NULL;
@@ -134,6 +135,17 @@ _PyObject_CallNoArg(PyObject *func) {
134135
return _PyObject_Vectorcall(func, NULL, 0, NULL);
135136
}
136137

138+
static inline PyObject *
139+
_PyObject_CallOneArg(PyObject *func, PyObject *arg)
140+
{
141+
assert(arg != NULL);
142+
PyObject *_args[2];
143+
PyObject **args = _args + 1; // For PY_VECTORCALL_ARGUMENTS_OFFSET
144+
args[0] = arg;
145+
return _PyObject_Vectorcall(func, args,
146+
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
147+
}
148+
137149
PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
138150
PyObject *callable,
139151
PyObject *obj,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add new function ``_PyObject_CallOneArg`` for calling an object with one
2+
positional argument.

Modules/_asynciomodule.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ _is_coroutine(PyObject *coro)
141141
Do this check after 'future_init()'; in case we need to raise
142142
an error, __del__ needs a properly initialized object.
143143
*/
144-
PyObject *res = PyObject_CallFunctionObjArgs(
145-
asyncio_iscoroutine_func, coro, NULL);
144+
PyObject *res = _PyObject_CallOneArg(asyncio_iscoroutine_func, coro);
146145
if (res == NULL) {
147146
return -1;
148147
}
@@ -1286,8 +1285,7 @@ static PyObject *
12861285
_asyncio_Future__repr_info_impl(FutureObj *self)
12871286
/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
12881287
{
1289-
return PyObject_CallFunctionObjArgs(
1290-
asyncio_future_repr_info_func, self, NULL);
1288+
return _PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
12911289
}
12921290

12931291
static PyObject *
@@ -1364,7 +1362,7 @@ FutureObj_finalize(FutureObj *fut)
13641362

13651363
func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
13661364
if (func != NULL) {
1367-
PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
1365+
PyObject *res = _PyObject_CallOneArg(func, context);
13681366
if (res == NULL) {
13691367
PyErr_WriteUnraisable(func);
13701368
}
@@ -2104,13 +2102,13 @@ _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
21042102
Py_DECREF(current_task_func);
21052103
return NULL;
21062104
}
2107-
ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2105+
ret = _PyObject_CallOneArg(current_task_func, loop);
21082106
Py_DECREF(current_task_func);
21092107
Py_DECREF(loop);
21102108
return ret;
21112109
}
21122110
else {
2113-
ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL);
2111+
ret = _PyObject_CallOneArg(current_task_func, loop);
21142112
Py_DECREF(current_task_func);
21152113
return ret;
21162114
}
@@ -2146,7 +2144,7 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
21462144
return NULL;
21472145
}
21482146

2149-
res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL);
2147+
res = _PyObject_CallOneArg(all_tasks_func, loop);
21502148
Py_DECREF(all_tasks_func);
21512149
return res;
21522150
}
@@ -2159,8 +2157,7 @@ static PyObject *
21592157
_asyncio_Task__repr_info_impl(TaskObj *self)
21602158
/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
21612159
{
2162-
return PyObject_CallFunctionObjArgs(
2163-
asyncio_task_repr_info_func, self, NULL);
2160+
return _PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
21642161
}
21652162

21662163
/*[clinic input]
@@ -2411,7 +2408,7 @@ TaskObj_finalize(TaskObj *task)
24112408

24122409
func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
24132410
if (func != NULL) {
2414-
PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
2411+
PyObject *res = _PyObject_CallOneArg(func, context);
24152412
if (res == NULL) {
24162413
PyErr_WriteUnraisable(func);
24172414
}
@@ -2543,7 +2540,7 @@ task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
25432540
return NULL;
25442541
}
25452542

2546-
PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
2543+
PyObject *e = _PyObject_CallOneArg(et, msg);
25472544
Py_DECREF(msg);
25482545
if (e == NULL) {
25492546
return NULL;

Modules/_collectionsmodule.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,7 @@ deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored))
512512
return NULL;
513513
}
514514
if (old_deque->maxlen < 0)
515-
result = PyObject_CallFunctionObjArgs((PyObject *)(Py_TYPE(deque)),
516-
deque, NULL);
515+
result = _PyObject_CallOneArg((PyObject *)(Py_TYPE(deque)), deque);
517516
else
518517
result = PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi",
519518
deque, old_deque->maxlen, NULL);

Modules/_csv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1240,7 +1240,7 @@ csv_writerow(WriterObj *self, PyObject *seq)
12401240
if (line == NULL) {
12411241
return NULL;
12421242
}
1243-
result = PyObject_CallFunctionObjArgs(self->write, line, NULL);
1243+
result = _PyObject_CallOneArg(self->write, line);
12441244
Py_DECREF(line);
12451245
return result;
12461246
}

Modules/_ctypes/callproc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker)
925925
if (!checker || !retval)
926926
return retval;
927927

928-
v = PyObject_CallFunctionObjArgs(checker, retval, NULL);
928+
v = _PyObject_CallOneArg(checker, retval);
929929
if (v == NULL)
930930
_PyTraceback_Add("GetResult", "_ctypes/callproc.c", __LINE__-2);
931931
Py_DECREF(retval);
@@ -1118,7 +1118,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
11181118
if (argtypes && argtype_count > i) {
11191119
PyObject *v;
11201120
converter = PyTuple_GET_ITEM(argtypes, i);
1121-
v = PyObject_CallFunctionObjArgs(converter, arg, NULL);
1121+
v = _PyObject_CallOneArg(converter, arg);
11221122
if (v == NULL) {
11231123
_ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1);
11241124
goto cleanup;
@@ -1795,15 +1795,15 @@ pointer(PyObject *self, PyObject *arg)
17951795

17961796
typ = PyDict_GetItemWithError(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg));
17971797
if (typ) {
1798-
return PyObject_CallFunctionObjArgs(typ, arg, NULL);
1798+
return _PyObject_CallOneArg(typ, arg);
17991799
}
18001800
else if (PyErr_Occurred()) {
18011801
return NULL;
18021802
}
18031803
typ = POINTER(NULL, (PyObject *)Py_TYPE(arg));
18041804
if (typ == NULL)
18051805
return NULL;
1806-
result = PyObject_CallFunctionObjArgs(typ, arg, NULL);
1806+
result = _PyObject_CallOneArg(typ, arg);
18071807
Py_DECREF(typ);
18081808
return result;
18091809
}

Modules/_elementtree.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,7 +2696,7 @@ treebuilder_append_event(TreeBuilderObject *self, PyObject *action,
26962696
PyObject *event = PyTuple_Pack(2, action, node);
26972697
if (event == NULL)
26982698
return -1;
2699-
res = _PyObject_FastCall(self->events_append, &event, 1);
2699+
res = _PyObject_CallOneArg(self->events_append, event);
27002700
Py_DECREF(event);
27012701
if (res == NULL)
27022702
return -1;
@@ -2859,7 +2859,7 @@ treebuilder_handle_comment(TreeBuilderObject* self, PyObject* text)
28592859
}
28602860

28612861
if (self->comment_factory) {
2862-
comment = _PyObject_FastCall(self->comment_factory, &text, 1);
2862+
comment = _PyObject_CallOneArg(self->comment_factory, text);
28632863
if (!comment)
28642864
return NULL;
28652865

@@ -3197,7 +3197,7 @@ expat_set_error(enum XML_Error error_code, Py_ssize_t line, Py_ssize_t column,
31973197
if (errmsg == NULL)
31983198
return;
31993199

3200-
error = _PyObject_FastCall(st->parseerror_obj, &errmsg, 1);
3200+
error = _PyObject_CallOneArg(st->parseerror_obj, errmsg);
32013201
Py_DECREF(errmsg);
32023202
if (!error)
32033203
return;
@@ -3260,7 +3260,7 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
32603260
(TreeBuilderObject*) self->target, value
32613261
);
32623262
else if (self->handle_data)
3263-
res = _PyObject_FastCall(self->handle_data, &value, 1);
3263+
res = _PyObject_CallOneArg(self->handle_data, value);
32643264
else
32653265
res = NULL;
32663266
Py_XDECREF(res);
@@ -3371,7 +3371,7 @@ expat_data_handler(XMLParserObject* self, const XML_Char* data_in,
33713371
/* shortcut */
33723372
res = treebuilder_handle_data((TreeBuilderObject*) self->target, data);
33733373
else if (self->handle_data)
3374-
res = _PyObject_FastCall(self->handle_data, &data, 1);
3374+
res = _PyObject_CallOneArg(self->handle_data, data);
33753375
else
33763376
res = NULL;
33773377

@@ -3398,7 +3398,7 @@ expat_end_handler(XMLParserObject* self, const XML_Char* tag_in)
33983398
else if (self->handle_end) {
33993399
tag = makeuniversal(self, tag_in);
34003400
if (tag) {
3401-
res = _PyObject_FastCall(self->handle_end, &tag, 1);
3401+
res = _PyObject_CallOneArg(self->handle_end, tag);
34023402
Py_DECREF(tag);
34033403
}
34043404
}
@@ -3485,7 +3485,7 @@ expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
34853485
if (!prefix)
34863486
return;
34873487

3488-
res = _PyObject_FastCall(self->handle_end_ns, &prefix, 1);
3488+
res = _PyObject_CallOneArg(self->handle_end_ns, prefix);
34893489
Py_DECREF(prefix);
34903490
}
34913491

@@ -3515,7 +3515,7 @@ expat_comment_handler(XMLParserObject* self, const XML_Char* comment_in)
35153515
if (!comment)
35163516
return;
35173517

3518-
res = _PyObject_FastCall(self->handle_comment, &comment, 1);
3518+
res = _PyObject_CallOneArg(self->handle_comment, comment);
35193519
}
35203520

35213521
Py_XDECREF(res);

Modules/_io/iobase.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit)
557557
PyObject *b;
558558

559559
if (peek != NULL) {
560-
PyObject *readahead = PyObject_CallFunctionObjArgs(peek, _PyLong_One, NULL);
560+
PyObject *readahead = _PyObject_CallOneArg(peek, _PyLong_One);
561561
if (readahead == NULL) {
562562
/* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals()
563563
when EINTR occurs so we needn't do it ourselves. */

Modules/_json.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -818,14 +818,14 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
818818
*next_idx_ptr = idx + 1;
819819

820820
if (has_pairs_hook) {
821-
val = PyObject_CallFunctionObjArgs(s->object_pairs_hook, rval, NULL);
821+
val = _PyObject_CallOneArg(s->object_pairs_hook, rval);
822822
Py_DECREF(rval);
823823
return val;
824824
}
825825

826826
/* if object_hook is not None: rval = object_hook(rval) */
827827
if (s->object_hook != Py_None) {
828-
val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL);
828+
val = _PyObject_CallOneArg(s->object_hook, rval);
829829
Py_DECREF(rval);
830830
return val;
831831
}
@@ -931,7 +931,7 @@ _parse_constant(PyScannerObject *s, const char *constant, Py_ssize_t idx, Py_ssi
931931
return NULL;
932932

933933
/* rval = parse_constant(constant) */
934-
rval = PyObject_CallFunctionObjArgs(s->parse_constant, cstr, NULL);
934+
rval = _PyObject_CallOneArg(s->parse_constant, cstr);
935935
idx += PyUnicode_GET_LENGTH(cstr);
936936
Py_DECREF(cstr);
937937
*next_idx_ptr = idx;
@@ -1030,7 +1030,7 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_
10301030
idx - start);
10311031
if (numstr == NULL)
10321032
return NULL;
1033-
rval = PyObject_CallFunctionObjArgs(custom_func, numstr, NULL);
1033+
rval = _PyObject_CallOneArg(custom_func, numstr);
10341034
}
10351035
else {
10361036
Py_ssize_t i, n;
@@ -1440,7 +1440,7 @@ encoder_encode_string(PyEncoderObject *s, PyObject *obj)
14401440
if (s->fast_encode) {
14411441
return s->fast_encode(NULL, obj);
14421442
}
1443-
encoded = PyObject_CallFunctionObjArgs(s->encoder, obj, NULL);
1443+
encoded = _PyObject_CallOneArg(s->encoder, obj);
14441444
if (encoded != NULL && !PyUnicode_Check(encoded)) {
14451445
PyErr_Format(PyExc_TypeError,
14461446
"encoder() must return a string, not %.80s",
@@ -1526,7 +1526,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc,
15261526
return -1;
15271527
}
15281528
}
1529-
newobj = PyObject_CallFunctionObjArgs(s->defaultfn, obj, NULL);
1529+
newobj = _PyObject_CallOneArg(s->defaultfn, obj);
15301530
if (newobj == NULL) {
15311531
Py_XDECREF(ident);
15321532
return -1;

Modules/_pickle.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ _Pickle_FastCall(PyObject *func, PyObject *obj)
359359
{
360360
PyObject *result;
361361

362-
result = PyObject_CallFunctionObjArgs(func, obj, NULL);
362+
result = _PyObject_CallOneArg(func, obj);
363363
Py_DECREF(obj);
364364
return result;
365365
}
@@ -420,7 +420,7 @@ call_method(PyObject *func, PyObject *self, PyObject *obj)
420420
return PyObject_CallFunctionObjArgs(func, self, obj, NULL);
421421
}
422422
else {
423-
return PyObject_CallFunctionObjArgs(func, obj, NULL);
423+
return _PyObject_CallOneArg(func, obj);
424424
}
425425
}
426426

@@ -2296,7 +2296,7 @@ _Pickler_write_bytes(PicklerObject *self,
22962296
return -1;
22972297
}
22982298
}
2299-
result = PyObject_CallFunctionObjArgs(self->write, payload, NULL);
2299+
result = _PyObject_CallOneArg(self->write, payload);
23002300
Py_XDECREF(mem);
23012301
if (result == NULL) {
23022302
return -1;
@@ -2504,8 +2504,7 @@ save_picklebuffer(PicklerObject *self, PyObject *obj)
25042504
}
25052505
int in_band = 1;
25062506
if (self->buffer_callback != NULL) {
2507-
PyObject *ret = PyObject_CallFunctionObjArgs(self->buffer_callback,
2508-
obj, NULL);
2507+
PyObject *ret = _PyObject_CallOneArg(self->buffer_callback, obj);
25092508
if (ret == NULL) {
25102509
return -1;
25112510
}
@@ -4322,8 +4321,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
43224321
* regular reduction mechanism.
43234322
*/
43244323
if (self->reducer_override != NULL) {
4325-
reduce_value = PyObject_CallFunctionObjArgs(self->reducer_override,
4326-
obj, NULL);
4324+
reduce_value = _PyObject_CallOneArg(self->reducer_override, obj);
43274325
if (reduce_value == NULL) {
43284326
goto error;
43294327
}

Modules/_sqlite/cache.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,8 @@ void pysqlite_cache_dealloc(pysqlite_Cache* self)
112112
Py_TYPE(self)->tp_free((PyObject*)self);
113113
}
114114

115-
PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args)
115+
PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* key)
116116
{
117-
PyObject* key = args;
118117
pysqlite_Node* node;
119118
pysqlite_Node* ptr;
120119
PyObject* data;
@@ -184,6 +183,9 @@ PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args)
184183
}
185184
}
186185

186+
/* We cannot replace this by _PyObject_CallOneArg() since
187+
* PyObject_CallFunction() has a special case when using a
188+
* single tuple as argument. */
187189
data = PyObject_CallFunction(self->factory, "O", key);
188190

189191
if (!data) {

0 commit comments

Comments
 (0)