Skip to content

Commit fa20556

Browse files
committed
bpo-37645: review fixes
1 parent 2e1b44e commit fa20556

File tree

7 files changed

+55
-36
lines changed

7 files changed

+55
-36
lines changed

Doc/c-api/object.rst

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,6 @@ Object Protocol
197197
does not silently discard an active exception.
198198
199199
200-
.. c:function:: PyObject* _PyObject_FunctionStr(PyObject *func)
201-
202-
Return a user-friendly string representation of the function-like object
203-
*func*. This returns ``func.__qualname__ + "()"`` if there is a
204-
``__qualname__`` attribute and ``str(func)`` otherwise.
205-
Note that there is no check that *func* is actually callable.
206-
207-
.. versionadded:: 3.9
208-
209-
210200
.. c:function:: PyObject* PyObject_Bytes(PyObject *o)
211201
212202
.. index:: builtin: bytes

Lib/test/test_call.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,11 @@ def test_varargs7_kw(self):
209209
self.assertRaisesRegex(TypeError, msg, next, x=2)
210210

211211
def test_varargs8_kw(self):
212-
msg = r"^pack\(\) takes no keyword arguments$"
212+
msg = r"^_struct[.]pack\(\) takes no keyword arguments$"
213213
self.assertRaisesRegex(TypeError, msg, struct.pack, x=2)
214214

215215
def test_varargs9_kw(self):
216-
msg = r"^pack_into\(\) takes no keyword arguments$"
216+
msg = r"^_struct[.]pack_into\(\) takes no keyword arguments$"
217217
self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2)
218218

219219
def test_varargs10_kw(self):

Lib/test/test_descr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1967,7 +1967,7 @@ def test_methods_in_c(self):
19671967
# different error messages.
19681968
set_add = set.add
19691969

1970-
expected_errmsg = "set.add() needs an argument"
1970+
expected_errmsg = "unbound method set.add() needs an argument"
19711971

19721972
with self.assertRaises(TypeError) as cm:
19731973
set_add()

Lib/test/test_extcall.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
>>> g(*Nothing())
119119
Traceback (most recent call last):
120120
...
121-
TypeError: g() argument after * must be an iterable, not Nothing
121+
TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing
122122
123123
>>> class Nothing:
124124
... def __len__(self): return 5
@@ -127,7 +127,7 @@
127127
>>> g(*Nothing())
128128
Traceback (most recent call last):
129129
...
130-
TypeError: g() argument after * must be an iterable, not Nothing
130+
TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing
131131
132132
>>> class Nothing():
133133
... def __len__(self): return 5
@@ -247,17 +247,17 @@
247247
>>> h(*h)
248248
Traceback (most recent call last):
249249
...
250-
TypeError: h() argument after * must be an iterable, not function
250+
TypeError: test.test_extcall.h() argument after * must be an iterable, not function
251251
252252
>>> h(1, *h)
253253
Traceback (most recent call last):
254254
...
255-
TypeError: h() argument after * must be an iterable, not function
255+
TypeError: test.test_extcall.h() argument after * must be an iterable, not function
256256
257257
>>> h(*[1], *h)
258258
Traceback (most recent call last):
259259
...
260-
TypeError: h() argument after * must be an iterable, not function
260+
TypeError: test.test_extcall.h() argument after * must be an iterable, not function
261261
262262
>>> dir(*h)
263263
Traceback (most recent call last):

Objects/descrobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObj
239239
PyObject *funcstr = _PyObject_FunctionStr(func);
240240
if (funcstr != NULL) {
241241
PyErr_Format(PyExc_TypeError,
242-
"%U needs an argument", funcstr);
242+
"unbound method %U needs an argument", funcstr);
243243
Py_DECREF(funcstr);
244244
}
245245
return -1;

Objects/object.c

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -665,28 +665,56 @@ PyObject_Bytes(PyObject *v)
665665

666666

667667
/*
668-
def _PyObject_FunctionStr(f):
668+
def _PyObject_FunctionStr(x):
669669
try:
670-
return f.__qualname__ + "()"
671-
except Exception:
672-
return str(f)
670+
qualname = x.__qualname__
671+
except AttributeError:
672+
return str(x)
673+
try:
674+
mod = x.__module__
675+
if mod is not None and mod != 'builtins':
676+
return f"{x.__module__}.{qualname}()"
677+
except AttributeError:
678+
pass
679+
return qualname
673680
*/
674681
PyObject *
675-
_PyObject_FunctionStr(PyObject *f)
682+
_PyObject_FunctionStr(PyObject *x)
676683
{
684+
_Py_IDENTIFIER(__module__);
677685
_Py_IDENTIFIER(__qualname__);
678-
PyObject *name = _PyObject_GetAttrId(f, &PyId___qualname__);
679-
if (name != NULL) {
680-
PyObject *res = PyUnicode_FromFormat("%S()", name);
681-
Py_DECREF(name);
682-
return res;
686+
_Py_IDENTIFIER(builtins);
687+
assert(!PyErr_Occurred());
688+
PyObject *qualname;
689+
int ret = _PyObject_LookupAttrId(x, &PyId___qualname__, &qualname);
690+
if (qualname == NULL) {
691+
if (ret < 0) {
692+
return NULL;
693+
}
694+
return PyObject_Str(x);
695+
}
696+
PyObject *module;
697+
PyObject *result = NULL;
698+
ret = _PyObject_LookupAttrId(x, &PyId___module__, &module);
699+
if (module != NULL && module != Py_None) {
700+
PyObject *builtinsname = _PyUnicode_FromId(&PyId_builtins);
701+
if (builtinsname == NULL) {
702+
goto done;
703+
}
704+
ret = PyObject_RichCompareBool(module, builtinsname, Py_NE);
705+
if (ret > 0) {
706+
result = PyUnicode_FromFormat("%S.%S()", module, qualname);
707+
goto done;
708+
}
683709
}
684-
/* __qualname__ lookup failed */
685-
if (!PyErr_ExceptionMatches(PyExc_Exception)) {
686-
return NULL;
710+
else if (ret < 0) {
711+
goto done;
687712
}
688-
PyErr_Clear();
689-
return PyObject_Str(f);
713+
result = PyUnicode_FromFormat("%S()", qualname);
714+
done:
715+
Py_DECREF(qualname);
716+
Py_XDECREF(module);
717+
return result;
690718
}
691719

692720
/* For Python 3.0.1 and later, the old three-way comparison has been

Python/ceval.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5341,8 +5341,9 @@ static int
53415341
check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args)
53425342
{
53435343
if (args->ob_type->tp_iter == NULL && !PySequence_Check(args)) {
5344-
/* check_args_iterable() may be called with a live exception,
5345-
* clear it. */
5344+
/* check_args_iterable() may be called with a live exception:
5345+
* clear it to prevent calling _PyObject_FunctionStr() with an
5346+
* exception set. */
53465347
PyErr_Clear();
53475348
PyObject *funcstr = _PyObject_FunctionStr(func);
53485349
if (funcstr != NULL) {

0 commit comments

Comments
 (0)