bpo-45083: Include the exception class qualname when formatting an ex…#28119
Conversation
erlend-aasland
left a comment
There was a problem hiding this comment.
I left some nitpicky code style remarks.
Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
|
🤖 New build scheduled with the buildbot fleet by @iritkatriel for commit 9781ce5 🤖 If you want to schedule another build, you need to add the ":hammer: test-with-buildbots" label again. |
|
In order to free qual name easily in patchdiff --git a/Python/errors.c b/Python/errors.c
index e390187215..cfa4275722 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -1287,14 +1287,6 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
}
assert(PyExceptionClass_Check(exc_type));
- PyObject *qualName = PyType_GetQualName((PyTypeObject *)exc_type);
- if (qualName == NULL) {
- return -1;
- }
- const char *className = PyUnicode_AsUTF8(qualName);
- if (!className) {
- return -1;
- }
PyObject *moduleName = _PyObject_GetAttrId(exc_type, &PyId___module__);
if (moduleName == NULL || !PyUnicode_Check(moduleName)) {
@@ -1319,13 +1311,22 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
Py_DECREF(moduleName);
}
}
- if (className == NULL) {
+
+ PyObject *qualname = PyType_GetQualName((PyTypeObject *)exc_type);
+ if (qualname == NULL) {
+ return -1;
+ }
+ const char *classname = PyUnicode_AsUTF8(qualname);
+ if (classname == NULL) {
+ Py_DECREF(qualname);
if (PyFile_WriteString("<unknown>", file) < 0) {
return -1;
}
}
else {
- if (PyFile_WriteString(className, file) < 0) {
+ int rc = PyFile_WriteString(classname, file);
+ Py_DECREF(qualname);
+ if (rc < 0) {
return -1;
}
}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index b4e34fb504..b5a3b6979b 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -962,23 +962,10 @@ print_exception(PyObject *f, PyObject *value)
}
else {
PyObject* moduleName;
- PyObject* qualName;
- const char *className = NULL;
_Py_IDENTIFIER(__module__);
assert(PyExceptionClass_Check(type));
- qualName = PyType_GetQualName((PyTypeObject *)type);
- if (!qualName) {
- PyErr_Clear();
- }
- else {
- className = PyUnicode_AsUTF8(qualName);
- if (!className) {
- PyErr_Clear();
- }
- }
-
moduleName = _PyObject_GetAttrId(type, &PyId___module__);
if (moduleName == NULL || !PyUnicode_Check(moduleName))
{
@@ -994,10 +981,20 @@ print_exception(PyObject *f, PyObject *value)
Py_DECREF(moduleName);
}
if (err == 0) {
- if (className == NULL)
+ PyObject *qualname = PyType_GetQualName((PyTypeObject *)type);
+ if (qualname == NULL) {
+ err = PyFile_WriteString("<unknown>", f);
+ }
+ else {
+ const char *classname = PyUnicode_AsUTF8(qualname);
+ if (classname == NULL) {
err = PyFile_WriteString("<unknown>", f);
- else
- err = PyFile_WriteString(className, f);
+ }
+ else {
+ err = PyFile_WriteString(classname, f);
+ }
+ Py_DECREF(qualname);
+ }
}
}
if (err == 0 && (value != Py_None)) { |
|
Do we not need to clear the error in this case?
|
I'm not sure; you probably know that better than me :) IIRC, the old code did not clear the error (on mobile right now, so I can't verify). |
| if (className == NULL) { | ||
|
|
||
| PyObject *qualname = PyType_GetQualName((PyTypeObject *)exc_type); | ||
| if (qualname == NULL || !PyUnicode_Check(qualname)) { |
There was a problem hiding this comment.
Sorry, one last nitpick :) Unless I've missed something in typeobject.c, qualname is always a unicode object. I suggest using an assert for the unicode check. Ditto for the check in pythonrun.c.
There was a problem hiding this comment.
I think that's correct, but I wasn't sure we want to assume it here (since this is error handling code, it needs to be very safe while it's not performance sensitive).
There is the same check above for modulename, I think there it is actually necessary.
I'm on the fence, wonder what others think.
There was a problem hiding this comment.
[...] since this is error handling code, it needs to be very safe while it's not performance sensitive
Good points!
There was a problem hiding this comment.
Well, you can't make __qualname__ anything else than a string from Python code:
>>> class C: ...
...
>>> C.__name__ = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign string to C.__name__, not 'int'
>>> C.__qualname__ = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign string to C.__qualname__, not 'int'
>>> C.__module__ = 1
>>>I don't mind keeping the check though as it's less dramatic than an assert failure. You're right that error handling isn't performance-sensitive.
There was a problem hiding this comment.
Additionally, this isn't even bona fide "error handling", it's literally about printing the exception out so totally no issue with keeping the additional check.
|
Confirmed no refleaks in |
|
Thanks @iritkatriel for the PR, and @ambv for merging it 🌮🎉.. I'm working now to backport this PR to: 3.9, 3.10. |
|
GH-28134 is a backport of this pull request to the 3.10 branch. |
|
GH-28135 is a backport of this pull request to the 3.9 branch. |
…ception (pythonGH-28119) Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
…ception (pythonGH-28119) Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
… an exception (GH-28119) (GH-28135) * bpo-45083: Include the exception class qualname when formatting an exception (GH-28119) Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Co-authored-by: Łukasz Langa <lukasz@langa.pl>
…g an exception (GH-28119) (GH-28134) Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> * Use a private version of _PyType_GetQualName Co-authored-by: Łukasz Langa <lukasz@langa.pl>
…ception
https://bugs.python.org/issue45083