Skip to content

Commit bba2239

Browse files
bpo-31572: Get rid of _PyObject_HasAttrId() in the ASDL parser. (#3725)
Silence only expected AttributeError.
1 parent 60c3d35 commit bba2239

File tree

2 files changed

+802
-628
lines changed

2 files changed

+802
-628
lines changed

Parser/asdl_c.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -497,18 +497,15 @@ def isSimpleType(self, field):
497497

498498
def visitField(self, field, name, sum=None, prod=None, depth=0):
499499
ctype = get_c_type(field.type)
500-
if field.opt:
501-
check = "exists_not_none(obj, &PyId_%s)" % (field.name,)
500+
if not field.opt:
501+
self.emit("tmp = _PyObject_GetAttrId(obj, &PyId_%s);" % field.name, depth)
502502
else:
503-
check = "_PyObject_HasAttrId(obj, &PyId_%s)" % (field.name,)
504-
self.emit("if (%s) {" % (check,), depth, reflow=False)
503+
self.emit("tmp = get_not_none(obj, &PyId_%s);" % field.name, depth)
504+
self.emit("if (tmp != NULL) {", depth)
505505
self.emit("int res;", depth+1)
506506
if field.seq:
507507
self.emit("Py_ssize_t len;", depth+1)
508508
self.emit("Py_ssize_t i;", depth+1)
509-
self.emit("tmp = _PyObject_GetAttrId(obj, &PyId_%s);" % field.name, depth+1)
510-
self.emit("if (tmp == NULL) goto failed;", depth+1)
511-
if field.seq:
512509
self.emit("if (!PyList_Check(tmp)) {", depth+1)
513510
self.emit("PyErr_Format(PyExc_TypeError, \"%s field \\\"%s\\\" must "
514511
"be a list, not a %%.200s\", tmp->ob_type->tp_name);" %
@@ -542,13 +539,19 @@ def visitField(self, field, name, sum=None, prod=None, depth=0):
542539
self.emit("if (res != 0) goto failed;", depth+1)
543540

544541
self.emit("Py_CLEAR(tmp);", depth+1)
545-
self.emit("} else {", depth)
546542
if not field.opt:
543+
self.emit("} else {", depth)
544+
self.emit("if (PyErr_ExceptionMatches(PyExc_AttributeError)) {", depth+1)
547545
message = "required field \\\"%s\\\" missing from %s" % (field.name, name)
548546
format = "PyErr_SetString(PyExc_TypeError, \"%s\");"
549-
self.emit(format % message, depth+1, reflow=False)
547+
self.emit(format % message, depth+2, reflow=False)
548+
self.emit("}", depth+1)
550549
self.emit("return 1;", depth+1)
551550
else:
551+
self.emit("} else if (PyErr_Occurred()) {", depth)
552+
self.emit("return 1;", depth+1)
553+
self.emit("} else {", depth)
554+
552555
if self.isNumeric(field):
553556
self.emit("%s = 0;" % field.name, depth+1)
554557
elif not self.isSimpleType(field):
@@ -660,13 +663,17 @@ def visitModule(self, mod):
660663
int res = -1;
661664
PyObject *key, *value, *fields;
662665
fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields);
663-
if (!fields)
664-
PyErr_Clear();
665666
if (fields) {
666667
numfields = PySequence_Size(fields);
667668
if (numfields == -1)
668669
goto cleanup;
669670
}
671+
else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
672+
PyErr_Clear();
673+
}
674+
else {
675+
goto cleanup;
676+
}
670677
671678
res = 0; /* if no error occurs, this stays 0 to the end */
672679
if (numfields < PyTuple_GET_SIZE(args)) {
@@ -958,17 +965,20 @@ def visitModule(self, mod):
958965
return 0;
959966
}
960967
961-
static int exists_not_none(PyObject *obj, _Py_Identifier *id)
968+
static PyObject *get_not_none(PyObject *obj, _Py_Identifier *id)
962969
{
963-
int isnone;
964970
PyObject *attr = _PyObject_GetAttrId(obj, id);
965971
if (!attr) {
966-
PyErr_Clear();
967-
return 0;
972+
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
973+
PyErr_Clear();
974+
}
975+
return NULL;
976+
}
977+
else if (attr == Py_None) {
978+
Py_DECREF(attr);
979+
return NULL;
968980
}
969-
isnone = attr == Py_None;
970-
Py_DECREF(attr);
971-
return !isnone;
981+
return attr;
972982
}
973983
974984
""", 0, reflow=False)

0 commit comments

Comments
 (0)