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 { ...@@ -322,18 +322,20 @@ extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept {
return d->getOrNull(key); return d->getOrNull(key);
} }
// XXX this would be easy to make much faster. auto&& tstate = _PyThreadState_Current;
if (tstate != NULL && tstate->curexc_type != NULL) {
// This path doesn't exist in CPython; we have it to support extension modules that do /* preserve the existing exception */
// something along the lines of PyDict_GetItem(PyModule_GetDict()): PyObject* err_type, *err_value, *err_tb;
try { PyErr_Fetch(&err_type, &err_value, &err_tb);
return getitem(dict, key); Box* b = getitemInternal<CAPI>(dict, key, NULL);
} catch (ExcInfo e) { /* ignore errors */
// PyDict_GetItem has special error behavior in CPython for backwards-compatibility reasons, PyErr_Restore(err_type, err_value, err_tb);
// and apparently it's important enough that we have to follow that. return b;
// The behavior is that all errors get suppressed, and in fact I think it's supposed to } else {
// restore the previous exception afterwards (we don't do that yet). Box* b = getitemInternal<CAPI>(dict, key, NULL);
return NULL; if (b == NULL)
PyErr_Clear();
return b;
} }
} }
......
...@@ -2289,7 +2289,7 @@ public: ...@@ -2289,7 +2289,7 @@ public:
return r; 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, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -2300,8 +2300,12 @@ public: ...@@ -2300,8 +2300,12 @@ public:
internStringMortalInplace(key); internStringMortalInplace(key);
Box* r = self->b->getattr(key); Box* r = self->b->getattr(key);
if (!r) if (!r) {
raiseExcHelper(KeyError, "'%s'", key->data()); if (S == CXX)
raiseExcHelper(KeyError, "'%s'", key->data());
else
PyErr_Format(KeyError, "'%s'", key->data());
}
return r; return r;
} }
...@@ -3842,7 +3846,8 @@ void setupRuntime() { ...@@ -3842,7 +3846,8 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::setitem, UNKNOWN, 3))); attrwrapper_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::setitem, UNKNOWN, 3)));
attrwrapper_cls->giveAttr( attrwrapper_cls->giveAttr(
"pop", new BoxedFunction(boxRTFunction((void*)AttrWrapper::pop, UNKNOWN, 3, false, false), { NULL })); "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("__delitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::delitem, UNKNOWN, 2)));
attrwrapper_cls->giveAttr("setdefault", attrwrapper_cls->giveAttr("setdefault",
new BoxedFunction(boxRTFunction((void*)AttrWrapper::setdefault, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)AttrWrapper::setdefault, UNKNOWN, 3)));
...@@ -3868,6 +3873,7 @@ void setupRuntime() { ...@@ -3868,6 +3873,7 @@ void setupRuntime() {
new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 1, true, true))); new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 1, true, true)));
attrwrapper_cls->freeze(); attrwrapper_cls->freeze();
attrwrapper_cls->tp_iter = AttrWrapper::iter; attrwrapper_cls->tp_iter = AttrWrapper::iter;
attrwrapper_cls->tp_as_mapping->mp_subscript = (binaryfunc)AttrWrapper::getitem<CAPI>;
attrwrapperiter_cls->giveAttr("__hasnext__", attrwrapperiter_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::hasnext, UNKNOWN, 1))); 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