8000 bpo-37337: Add _PyObject_CallMethodNoArgs() by jdemeyer · Pull Request #14267 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-37337: Add _PyObject_CallMethodNoArgs() #14267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 8, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
bpo-37337: Add _PyObject_CallMethodNoArgs()
  • Loading branch information
jdemeyer committed Jul 1, 2019
commit 338f5575ac80346e34fc4624c767fd2f43dd073a
11 changes: 11 additions & 0 deletions Doc/c-api/object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,17 @@ Object Protocol
*NULL* on failure.


.. c:function:: PyObject* _PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)

Call a method of the Python object *obj* without arguments,
where the name of the method is given as a Python string object in *name*.

Return the result of the call on success, or raise an exception and return
*NULL* on failure.

.. versionadded:: 3.9


.. c:function:: PyObject* _PyObject_Vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)

Call a callable Python object *callable*, using
Expand Down
16 changes: 16 additions & 0 deletions Include/cpython/abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ PyAPI_FUNC(PyObject *) _PyObject_VectorcallMethod(
PyObject *name, PyObject *const *args,
size_t nargsf, PyObject *kwnames);

static inline PyObject *
_PyObject_CallMethodNoArgs(PyObject *self, PyObject *name)
{
PyObject *args[1] = {self};
return _PyObject_VectorcallMethod(name, args,
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
}

/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
as the method name. */
PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj,
Expand Down Expand Up @@ -190,6 +198,14 @@ _PyObject_VectorcallMethodId(
return _PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
}

static inline PyObject *
_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
{
PyObject *args[1] = {self};
return _PyOb EDBE ject_VectorcallMethodId(name, args,
1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
}

PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o);

/* Guess the size of object 'o' using len(o) or o.__length_hint__().
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Add :c:func:`_PyObject_VectorcallMethod` for fast calling of methods.
Add fast functions for calling methods: :c:func:`_PyObject_VectorcallMethod`
and :c:func:`_PyObject_CallMethodNoArgs`
16 changes: 7 additions & 9 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ get_event_loop(void)
return NULL;
}

loop = _PyObject_CallMethodId(policy, &PyId_get_event_loop, NULL);
loop = _PyObject_CallMethodIdNoArgs(policy, &PyId_get_event_loop);
Py_DECREF(policy);
return loop;
}
Expand Down Expand Up @@ -494,7 +494,7 @@ future_init(FutureObj *fut, PyObject *loop)
}
fut->fut_loop = loop;

res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
res = _PyObject_CallMethodIdNoArgs(fut->fut_loop, &PyId_get_debug);
if (res == NULL) {
return -1;
}
Expand Down Expand Up @@ -1297,9 +1297,8 @@ FutureObj_repr(FutureObj *fut)

ENSURE_FUTURE_ALIVE(fut)

PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
&PyId__repr_info,
NULL);
PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
&PyId__repr_info);
if (rinfo == NULL) {
return NULL;
}
Expand Down Expand Up @@ -2200,8 +2199,7 @@ _asyncio_Task_cancel_impl(TaskObj *self)
PyObject *res;
int is_true;

res = _PyObject_CallMethodId(
self->task_fut_waiter, &PyId_cancel, NULL);
res = _PyObject_CallMethodIdNoArgs(self->task_fut_waiter, &PyId_cancel);
if (res == NULL) {
return NULL;
}
Expand Down Expand Up @@ -2738,7 +2736,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
if (task->task_must_cancel) {
PyObject *r;
int is_true;
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
if (r == NULL) {
return NULL;
}
Expand Down Expand Up @@ -2829,7 +2827,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
if (task->task_must_cancel) {
PyObject *r;
int is_true;
r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
r = _PyObject_CallMethodIdNoArgs(result, &PyId_cancel);
if (r == NULL) {
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion Modules/_collectionsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2040,7 +2040,7 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored))
args = PyTuple_Pack(1, dd->default_factory);
if (args == NULL)
return NULL;
items = _PyObject_CallMethodId((PyObject *)dd, &PyId_items, NULL);
items = _PyObject_CallMethodIdNoArgs((PyObject *)dd, &PyId_items);
if (items == NULL) {
Py_DECREF(args);
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3974,7 +3974,7 @@ _build_result(PyObject *result, PyObject *callargs,
_Py_IDENTIFIER(__ctypes_from_outparam__);

v = PyTuple_GET_ITEM(callargs, i);
v = _PyObject_CallMethodId 10000 (v, &PyId___ctypes_from_outparam__, NULL);
v = _PyObject_CallMethodIdNoArgs(v, &PyId___ctypes_from_outparam__);
if (v == NULL || numretvals == 1) {
Py_DECREF(callargs);
return v;
Expand Down
2 changes: 1 addition & 1 deletion Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2906,7 +2906,7 @@ _curses_getwin(PyObject *module, PyObject *file)
if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
goto error;

data = _PyObject_CallMethodId(file, &PyId_read, NULL);
data = _PyObject_CallMethodIdNoArgs(file, &PyId_read);
if (data == NULL)
goto error;
if (!PyBytes_Check(data)) {
Expand Down
10 changes: 5 additions & 5 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,7 @@ time_time(void)
if (time != NULL) {
_Py_IDENTIFIER(time);

result = _PyObject_CallMethodId(time, &PyId_time, NULL);
result = _PyObject_CallMethodIdNoArgs(time, &PyId_time);
Py_DECREF(time);
}
return result;
Expand Down Expand Up @@ -1918,7 +1918,7 @@ get_float_as_integer_ratio(PyObject *floatobj)
PyObject *ratio;

assert(floatobj && PyFloat_Check(floatobj));
ratio = _PyObject_CallMethodId(floatobj, &PyId_as_integer_ratio, NULL);
ratio = _PyObject_CallMethodIdNoArgs(floatobj, &PyId_as_integer_ratio);
if (ratio == NULL) {
return NULL;
}
Expand Down Expand Up @@ -3162,7 +3162,7 @@ date_isoformat(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
static PyObject *
date_str(PyDateTime_Date *self)
{
return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, NULL);
return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
}


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

tuple = _PyObject_CallMethodId((PyObject *)self, &PyId_timetuple, NULL);
tuple = _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_timetuple);
if (tuple == NULL)
return NULL;
result = wrap_strftime((PyObject *)self, format, tuple,
Expand Down Expand Up @@ -4175,7 +4175,7 @@ time_repr(PyDateTime_Time *self)
static PyObject *
time_str(PyDateTime_Time *self)
{
return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, NULL);
return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
}

static PyObject *
Expand Down
2 changes: 1 addition & 1 deletion Modules/_dbmmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ static PyObject *
dbm__exit__(PyObject *self, PyObject *args)
{
_Py_IDENTIFIER(close);
return _PyObject_CallMethodId(self, &PyId_close, NULL);
return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
}


Expand Down
2 changes: 1 addition & 1 deletion Modules/_gdbmmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ static PyObject *
dbm__exit__(PyObject *self, PyObject *args)
{
_Py_IDENTIFIER(close);
return _PyObject_CallMethodId(self, &PyId_close, NULL);
return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
}

static PyMethodDef dbm_methods[] = {
Expand Down
4 changes: 2 additions & 2 deletions Modules/_io/_iomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,

/* buffering */
if (buffering < 0) {
PyObject *res = _PyObject_CallMethodId(raw, &PyId_isatty, NULL);
PyObject *res = _PyObject_CallMethodIdNoArgs(raw, &PyId_isatty);
if (res == NULL)
goto error;
isatty = PyLong_AsLong(res);
Expand Down Expand Up @@ -494,7 +494,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
if (result != NULL) {
PyObject *exc, *val, *tb, *close_result;
PyErr_Fetch(&exc, &val, &tb);
close_result = _PyObject_CallMethodId(result, &PyId_close, NULL);
close_result = _PyObject_CallMethodIdNoArgs(result, &PyId_close);
_PyErr_ChainExceptions(exc, val, tb);
Py_XDECREF(close_result);
Py_DECREF(result);
Expand Down
26 changes: 13 additions & 13 deletions Modules/_io/bufferedio.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ static PyObject *
buffered_simple_flush(buffered *self, PyObject *args)
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_flush);
}

static int
Expand Down Expand Up @@ -513,15 +513,15 @@ buffered_close(buffered *self, PyObject *args)
}
/* flush() will most probably re-take the lock, so drop it first */
LEAVE_BUFFERED(self)
res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
if (!ENTER_BUFFERED(self))
return NULL;
if (res == NULL)
PyErr_Fetch(&exc, &val, &tb);
else
Py_DECREF(res);

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

if (self->buffer) {
PyMem_Free(self->buffer);
Expand All @@ -545,7 +545,7 @@ buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
{
PyObject *raw, *res;
CHECK_INITIALIZED(self)
res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
if (res == NULL)
return NULL;
Py_DECREF(res);
Expand All @@ -562,21 +562,21 @@ static PyObject *
buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_seekable);
}

static PyObject *
buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_readable);
}

static PyObject *
buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_writable);
}

static PyObject *
Expand All @@ -599,14 +599,14 @@ static PyObject *
buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_fileno);
}

static PyObject *
buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
{
CHECK_INITIALIZED(self)
return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
return _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_isatty);
}

/* Forward decls */
Expand Down Expand Up @@ -670,7 +670,7 @@ _buffered_raw_tell(buffered *self)
{
Py_off_t n;
PyObject *res;
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
res = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_tell);
if (res == NULL)
return -1;
n = PyNumber_AsOff_t(res, PyExc_ValueError);
Expand Down Expand Up @@ -1350,8 +1350,8 @@ buffered_iternext(buffered *self)
line = _buffered_readline(self, -1);
}
else {
line = PyObject_CallMethodObjArgs((PyObject *)self,
_PyIO_str_readline, NULL);
line = _PyObject_CallMethodNoArgs((PyObject *)self,
_PyIO_str_readline);
if (line && !PyBytes_Check(line)) {
PyErr_Format(PyExc_OSError,
"readline() should have returned a bytes object, "
Expand Down Expand Up @@ -1566,7 +1566,7 @@ _bufferedreader_read_all(buffered *self)
}

/* Read until EOF or until read() would block. */
data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
data = _PyObject_CallMethodNoArgs(self->raw, _PyIO_str_read);
if (data == NULL)
goto cleanup;
if (data != Py_None && !PyBytes_Check(data)) {
Expand Down
17 changes: 8 additions & 9 deletions Modules/_io/iobase.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ _io__IOBase_close_impl(PyObject *self)
Py_RETURN_NONE;
}

res = PyObject_CallMethodObjArgs(self, _PyIO_str_flush, NULL);
res = _PyObject_CallMethodNoArgs(self, _PyIO_str_flush);

PyErr_Fetch(&exc, &val, &tb);
rc = _PyObject_SetAttrId(self, &PyId___IOBase_closed, Py_True);
Expand Down Expand Up @@ -281,8 +281,7 @@ iobase_finalize(PyObject *self)
finalization process. */
if (_PyObject_SetAttrId(self, &PyId__finalizing, Py_True))
PyErr_Clear();
res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
NULL);
res = _PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_close);
/* Silencing I/O errors is bad, but printing spurious tracebacks is
equally as bad, and potentially more frequent (because of
shutdown issues). */
Expand Down Expand Up @@ -383,7 +382,7 @@ _io__IOBase_seekable_impl(PyObject *self)
PyObject *
_PyIOBase_check_seekable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_seekable, NULL);
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_seekable);
if (res == NULL)
return NULL;
if (res != Py_True) {
Expand Down Expand Up @@ -416,7 +415,7 @@ _io__IOBase_readable_impl(PyObject *self)
PyObject *
_PyIOBase_check_readable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_readable, NULL);
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_readable);
if (res == NULL)
return NULL;
if (res != Py_True) {
Expand Down Expand Up @@ -449,7 +448,7 @@ _io__IOBase_writable_impl(PyObject *self)
PyObject *
_PyIOBase_check_writable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_writable, NULL);
PyObject *res = _PyObject_CallMethodNoArgs(self, _PyIO_str_writable);
if (res == NULL)
return NULL;
if (res != Py_True) {
Expand Down Expand Up @@ -478,7 +477,7 @@ iobase_enter(PyObject *self, PyObject *args)
static PyObject *
iobase_exit(PyObject *self, PyObject *args)
{
return PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL);
return _PyObject_CallMethodNoArgs(self, _PyIO_str_close);
}

/* Lower-level APIs */
Expand Down Expand Up @@ -656,7 +655,7 @@ iobase_iter(PyObject *self)
static PyObject *
iobase_iternext(PyObject *self)
{
PyObject *line = PyObject_CallMethodObjArgs(self, _PyIO_str_readline, NULL);
PyObject *line = _PyObject_CallMethodNoArgs(self, _PyIO_str_readline);

if (line == NULL)
return NULL;
Expand Down Expand Up @@ -921,7 +920,7 @@ _io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n)
if (n < 0) {
_Py_IDENTIFIER(readall);

return _PyObject_CallMethodId(self, &PyId_readall, NULL);
return _PyObject_CallMethodIdNoArgs(self, &PyId_readall);
}

/* TODO: allocate a bytes object directly instead and manually construct
Expand Down
Loading
0