-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-45083: Include the exception class qualname when formatting an ex… #28119
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some nitpicky code style remarks.
Co-authored-by: Erlend Egeberg Aasland <[email protected]>
Co-authored-by: Erlend Egeberg Aasland <[email protected]>
Co-authored-by: Erlend Egeberg Aasland <[email protected]>
🤖 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...] 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 <[email protected]> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <[email protected]>
…ception (pythonGH-28119) Co-authored-by: Erlend Egeberg Aasland <[email protected]> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <[email protected]>
… 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 <[email protected]> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <[email protected]> Co-authored-by: Łukasz Langa <[email protected]>
…g an exception (GH-28119) (GH-28134) Co-authored-by: Erlend Egeberg Aasland <[email protected]> (cherry picked from commit b4b6342) Co-authored-by: Irit Katriel <[email protected]> * Use a private version of _PyType_GetQualName Co-authored-by: Łukasz Langa <[email protected]>
…ception
https://bugs.python.org/issue45083