Commit 7293439d authored by Marius Wachtler's avatar Marius Wachtler

Add attrwrapper_cls->tp_as_mapping->mp_subscript

This is an optimization but also fixes an lxml issue:
it calls AttrWrapper::getitem even though an error is currenly set. (which would assert if we do a callFunc call for the getitem)
parent 6e2c8463
......@@ -322,18 +322,20 @@ extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept {
return d->getOrNull(key);
}
// XXX this would be easy to make much faster.
// This path doesn't exist in CPython; we have it to support extension modules that do
// something along the lines of PyDict_GetItem(PyModule_GetDict()):
try {
return getitem(dict, key);
} catch (ExcInfo e) {
// PyDict_GetItem has special error behavior in CPython for backwards-compatibility reasons,
// and apparently it's important enough that we have to follow that.
// The behavior is that all errors get suppressed, and in fact I think it's supposed to
// restore the previous exception afterwards (we don't do that yet).
return NULL;
auto&& tstate = _PyThreadState_Current;
if (tstate != NULL && tstate->curexc_type != NULL) {
/* preserve the existing exception */
PyObject* err_type, *err_value, *err_tb;
PyErr_Fetch(&err_type, &err_value, &err_tb);
Box* b = getitemInternal<CAPI>(dict, key, NULL);
/* ignore errors */
PyErr_Restore(err_type, err_value, err_tb);
return b;
} else {
Box* b = getitemInternal<CAPI>(dict, key, NULL);
if (b == NULL)
PyErr_Clear();
return b;
}
}
......
......@@ -2289,7 +2289,7 @@ public:
return r;
}
static Box* getitem(Box* _self, Box* _key) {
template <ExceptionStyle S> static Box* getitem(Box* _self, Box* _key) noexcept(S == CAPI) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -2300,8 +2300,12 @@ public:
internStringMortalInplace(key);
Box* r = self->b->getattr(key);
if (!r)
raiseExcHelper(KeyError, "'%s'", key->data());
if (!r) {
if (S == CXX)
raiseExcHelper(KeyError, "'%s'", key->data());
else
PyErr_Format(KeyError, "'%s'", key->data());
}
return r;
}
......@@ -3842,7 +3846,8 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::setitem, UNKNOWN, 3)));
attrwrapper_cls->giveAttr(
"pop", new BoxedFunction(boxRTFunction((void*)AttrWrapper::pop, UNKNOWN, 3, false, false), { NULL }));
attrwrapper_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::getitem, UNKNOWN, 2)));
attrwrapper_cls->giveAttr("__getitem__",
new BoxedFunction(boxRTFunction((void*)AttrWrapper::getitem<CXX>, UNKNOWN, 2)));
attrwrapper_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::delitem, UNKNOWN, 2)));
attrwrapper_cls->giveAttr("setdefault",
new BoxedFunction(boxRTFunction((void*)AttrWrapper::setdefault, UNKNOWN, 3)));
......@@ -3868,6 +3873,7 @@ void setupRuntime() {
new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 1, true, true)));
attrwrapper_cls->freeze();
attrwrapper_cls->tp_iter = AttrWrapper::iter;
attrwrapper_cls->tp_as_mapping->mp_subscript = (binaryfunc)AttrWrapper::getitem<CAPI>;
attrwrapperiter_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::hasnext, UNKNOWN, 1)));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment