summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-07-18 07:01:22 (GMT)
committerGitHub <noreply@github.com>2023-07-18 07:01:22 (GMT)
commitd671c6567aa5b5c4478aadcd623f5c3b8261b5b1 (patch)
tree5a275ff9c7f6e72e51d3c6d67947e5f709105ec0
parente903c16a6c3fe0adb594f93acc56e719590c4790 (diff)
downloadcpython-d671c6567aa5b5c4478aadcd623f5c3b8261b5b1.zip
cpython-d671c6567aa5b5c4478aadcd623f5c3b8261b5b1.tar.gz
cpython-d671c6567aa5b5c4478aadcd623f5c3b8261b5b1.tar.bz2
[3.12] gh-106719: Fix __annotations__ getter and setter in the type and module types (GH-106720) (GH-106848)
gh-106719: Fix __annotations__ getter and setter in the type and module types (GH-106720) No longer suppress arbitrary errors. Simplify the code. (cherry picked from commit e1c295e3da9ff5a3eb6b009a1f821d80e564ac87) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-07-13-15-59-07.gh-issue-106719.jmVrsv.rst2
-rw-r--r--Objects/moduleobject.c48
-rw-r--r--Objects/typeobject.c32
3 files changed, 35 insertions, 47 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-13-15-59-07.gh-issue-106719.jmVrsv.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-13-15-59-07.gh-issue-106719.jmVrsv.rst
new file mode 100644
index 0000000..dc4bef1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-13-15-59-07.gh-issue-106719.jmVrsv.rst
@@ -0,0 +1,2 @@
+No longer suppress arbitrary errors in the ``__annotations__`` getter and
+setter in the type and module types.
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 985be58..4daf1a9 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -935,26 +935,20 @@ static PyObject *
module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored))
{
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
-
- if ((dict == NULL) || !PyDict_Check(dict)) {
+ if (dict == NULL) {
+ return NULL;
+ }
+ if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
- Py_XDECREF(dict);
+ Py_DECREF(dict);
return NULL;
}
- PyObject *annotations;
- /* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
- if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
- annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
- /*
- ** _PyDict_GetItemIdWithError could still fail,
- ** for instance with a well-timed Ctrl-C or a MemoryError.
- ** so let's be totally safe.
- */
- if (annotations) {
- Py_INCREF(annotations);
- }
- } else {
+ PyObject *annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
+ if (annotations) {
+ Py_INCREF(annotations);
+ }
+ else if (!PyErr_Occurred()) {
annotations = PyDict_New();
if (annotations) {
int result = PyDict_SetItem(
@@ -973,8 +967,10 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor
{
int ret = -1;
PyObject *dict = PyObject_GetAttr((PyObject *)m, &_Py_ID(__dict__));
-
- if ((dict == NULL) || !PyDict_Check(dict)) {
+ if (dict == NULL) {
+ return -1;
+ }
+ if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError, "<module>.__dict__ is not a dictionary");
goto exit;
}
@@ -982,19 +978,17 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor
if (value != NULL) {
/* set */
ret = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
- goto exit;
}
-
- /* delete */
- if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
- PyErr_Format(PyExc_AttributeError, "__annotations__");
- goto exit;
+ else {
+ /* delete */
+ ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
+ if (ret < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
+ PyErr_SetString(PyExc_AttributeError, "__annotations__");
+ }
}
- ret = PyDict_DelItem(dict, &_Py_ID(__annotations__));
-
exit:
- Py_XDECREF(dict);
+ Py_DECREF(dict);
return ret;
}
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 6662379..40e187d 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1449,24 +1449,17 @@ type_get_annotations(PyTypeObject *type, void *context)
}
PyObject *annotations;
- /* there's no _PyDict_GetItemId without WithError, so let's LBYL. */
PyObject *dict = lookup_tp_dict(type);
- if (PyDict_Contains(dict, &_Py_ID(__annotations__))) {
- annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
- /*
- ** PyDict_GetItemWithError could still fail,
- ** for instance with a well-timed Ctrl-C or a MemoryError.
- ** so let's be totally safe.
- */
- if (annotations) {
- if (Py_TYPE(annotations)->tp_descr_get) {
- annotations = Py_TYPE(annotations)->tp_descr_get(
- annotations, NULL, (PyObject *)type);
- } else {
- Py_INCREF(annotations);
- }
+ annotations = PyDict_GetItemWithError(dict, &_Py_ID(__annotations__));
+ if (annotations) {
+ if (Py_TYPE(annotations)->tp_descr_get) {
+ annotations = Py_TYPE(annotations)->tp_descr_get(
+ annotations, NULL, (PyObject *)type);
+ } else {
+ Py_INCREF(annotations);
}
- } else {
+ }
+ else if (!PyErr_Occurred()) {
annotations = PyDict_New();
if (annotations) {
int result = PyDict_SetItem(
@@ -1498,11 +1491,10 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
result = PyDict_SetItem(dict, &_Py_ID(__annotations__), value);
} else {
/* delete */
- if (!PyDict_Contains(dict, &_Py_ID(__annotations__))) {
- PyErr_Format(PyExc_AttributeError, "__annotations__");
- return -1;
- }
result = PyDict_DelItem(dict, &_Py_ID(__annotations__));
+ if (result < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
+ PyErr_SetString(PyExc_AttributeError, "__annotations__");
+ }
}
if (result == 0) {