10000 bpo-37645: add new function _PyObject_FunctionStr() by jdemeyer · Pull Request #14890 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-37645: add new function _PyObject_FunctionStr() #14890

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 9 commits into from
Nov 5, 2019
Prev Previous commit
Next Next commit
bpo-37645: rename PyObject_FunctionStr() -> _PyObject_FunctionStr()
  • Loading branch information
jdemeyer committed Aug 18, 2019
commit 4c0c877889b406d33a863005361afb1bd19149af
2 changes: 1 addition & 1 deletion
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ Object Protocol
does not silently discard an active exception.


.. c:function:: PyObject* PyObject_FunctionStr(PyObject *func)
.. c:function:: PyObject* _PyObject_FunctionStr(PyObject *func)

Return a user-friendly string representation of the function-like object
*func*. This returns ``func.__qualname__ + "()"`` if there is a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning __qualname__ without module is not particularly useful.

If you want to return a full qualified name (long but unambiguous), return __module__ + '.' + __qualname__. __module__ can be omitted if it is 'builtins'.

If you want to return a short name (it is enough in many times), return __name__.

if __qualname__ is not available, you can use __name__ instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if __qualname__ is not available, you can use __name__ instead.

This is mainly meant as replacement for PyEval_GetFuncName and all classes supported by that function implement __qualname__. So I see little reason for the additional complexity of supporting __name__.

Expand Down
2 changes: 1 addition & 1 deletion Include/cpython/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ static inline void _Py_Dealloc_inline(PyObject *op)
}
#define _Py_Dealloc(op) _Py_Dealloc_inline(op)

PyAPI_FUNC(PyObject *) PyObject_FunctionStr(PyObject *);
PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);

/* Safely decref `op` and set `op` to `op2`.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Add :c:func:`PyObject_FunctionStr` to get a user-friendly string representation
Add :c:func:`_PyObject_FunctionStr` to get a user-friendly string representation
of a function-like object.
8 changes: 4 additions & 4 deletions Objects/descrobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObj
{
assert(!PyErr_Occurred());
if (nargs < 1) {
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U needs an argument", funcstr);
Expand All @@ -250,7 +250,7 @@ method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObj
return -1;
}
if (kwnames && PyTuple_GET_SIZE(kwnames)) {
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes no keyword arguments", funcstr);
Expand Down Expand Up @@ -375,7 +375,7 @@ method_vectorcall_NOARGS(
return NULL;
}
if (nargs != 1) {
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes no arguments (%zd given)", funcstr, nargs-1);
Expand All @@ -401,7 +401,7 @@ method_vectorcall_O(
return NULL;
}
if (nargs != 2) {
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes exactly one argument (%zd given)",
Expand Down
6 changes: 3 additions & 3 deletions Objects/methodobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ cfunction_check_kwargs(PyObject *func, PyObject *kwnames)
assert(!PyErr_Occurred());
assert(PyCFunction_Check(func));
if (kwnames && PyTuple_GET_SIZE(kwnames)) {
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes no keyword arguments", funcstr);
Expand Down Expand Up @@ -403,7 +403,7 @@ cfunction_vectorcall_NOARGS(
}
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (nargs != 0) {
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes no arguments (%zd given)", funcstr, nargs);
Expand All @@ -429,7 +429,7 @@ cfunction_vectorcall_O(
}
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
if (nargs != 1) {
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
PyErr_Format(PyExc_TypeError,
"%U takes exactly one argument (%zd given)", funcstr, nargs);
Expand Down
6 changes: 2 additions & 4 deletions Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -665,14 +665,14 @@ PyObject_Bytes(PyObject *v)


/*
def PyObject_FunctionStr(f):
def _PyObject_FunctionStr(f):
try:
return f.__qualname__ + "()"
except Exception:
return type(f).__name__ + " object"
*/
PyObject *
PyObject_FunctionStr(PyObject *f)
_PyObject_FunctionStr(PyObject *f)
{
_Py_IDENTIFIER(__qualname__);
PyObject *name = _PyObject_GetAttrId(f, &PyId___qualname__);
Expand All @@ -683,8 +683,6 @@ PyObject_FunctionStr(PyObject *f)
}
/* __qualname__ lookup failed */
if (!PyErr_ExceptionMatches(PyExc_Exception)) {
/* An exception not inheriting from Exception, like KeyboardInterrupt.
* Propagate it. */
return NULL;
}
PyErr_Clear();
Expand Down
2 changes: 1 addition & 1 deletion Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -5344,7 +5344,7 @@ check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args)
/* check_args_iterable() may be called with a live exception,
* clear it. */
PyErr_Clear();
PyObject *funcstr = PyObject_FunctionStr(func);
PyObject *funcstr = _PyObject_FunctionStr(func);
if (funcstr != NULL) {
_PyErr_Format(tstate, PyExc_TypeError,
"%U argument after * must be an iterable, not %.200s",
Expand Down
0