Less lookups and more efficient calls in microprotocols_adapt().

Also more explicit handling of the exception indicator.
This commit is contained in:
Daniele Varrazzo 2010-11-09 02:38:59 +00:00
parent 753b580d72
commit 2dc28ee7d8

View File

@ -129,7 +129,7 @@ _get_superclass_adapter(PyObject *obj, PyObject *proto)
PyObject * PyObject *
microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
{ {
PyObject *adapter, *adapted, *key; PyObject *adapter, *adapted, *key, *meth;
char buffer[256]; char buffer[256];
/* we don't check for exact type conformance as specified in PEP 246 /* we don't check for exact type conformance as specified in PEP 246
@ -159,22 +159,42 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
} }
/* try to have the protocol adapt this object*/ /* try to have the protocol adapt this object*/
if (PyObject_HasAttrString(proto, "__adapt__")) { if ((meth = PyObject_GetAttrString(proto, "__adapt__"))) {
adapted = PyObject_CallMethod(proto, "__adapt__", "O", obj); adapted = PyObject_CallFunctionObjArgs(meth, obj, NULL);
Py_DECREF(meth);
if (adapted && adapted != Py_None) return adapted; if (adapted && adapted != Py_None) return adapted;
Py_XDECREF(adapted); Py_XDECREF(adapted);
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Clear();
} else {
return NULL; return NULL;
} }
}
}
else {
/* proto.__adapt__ not found. */
PyErr_Clear();
}
/* and finally try to have the object adapt itself */ /* and finally try to have the object adapt itself */
if (PyObject_HasAttrString(obj, "__conform__")) { if ((meth = PyObject_GetAttrString(obj, "__conform__"))) {
adapted = PyObject_CallMethod(obj, "__conform__","O", proto); adapted = PyObject_CallFunctionObjArgs(meth, proto, NULL);
Py_DECREF(meth);
if (adapted && adapted != Py_None) return adapted; if (adapted && adapted != Py_None) return adapted;
Py_XDECREF(adapted); Py_XDECREF(adapted);
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Clear();
} else {
return NULL; return NULL;
} }
}
}
else {
/* obj.__conform__ not found. */
PyErr_Clear();
}
/* else set the right exception and return NULL */ /* else set the right exception and return NULL */
PyOS_snprintf(buffer, 255, "can't adapt type '%s'", obj->ob_type->tp_name); PyOS_snprintf(buffer, 255, "can't adapt type '%s'", obj->ob_type->tp_name);