BGE Python API

improved how attribute errors are set so each classes py_getattro function dosnt need to set an error if the attribute doesn't exist.
Now py_base_getattro sets an error on a NULL return value when no errors are set to avoid setting errors at multiple levels.
This commit is contained in:
Campbell Barton
2009-04-22 09:47:57 +00:00
parent 95038048a2
commit 785b784e09
3 changed files with 25 additions and 13 deletions

View File

@@ -146,9 +146,23 @@ PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr)
PyObject *ret= self_plus->py_getattro(attr); PyObject *ret= self_plus->py_getattro(attr);
if(ret==NULL && (strcmp(PyString_AsString(attr), "__dict__")==0)) /* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */
ret= self_plus->py_getattro_dict(); if(ret==NULL) {
char *attr_str= PyString_AsString(attr);
if (strcmp(attr_str, "__dict__")==0)
{
/* the error string will probably not
* be set but just incase clear it */
PyErr_Clear();
ret= self_plus->py_getattro_dict();
}
else if (!PyErr_Occurred()) {
/* We looked for an attribute but it wasnt found
* since py_getattro didnt set the error, set it here */
PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str);
}
}
return ret; return ret;
} }
@@ -183,8 +197,7 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr)
{ {
PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
if (descr == NULL) { if (descr == NULL) {
PyErr_Format(PyExc_AttributeError, "attribute \"%s\" not found", PyString_AsString(attr)); return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */
return NULL;
} else { } else {
/* Copied from py_getattro_up */ /* Copied from py_getattro_up */
if (PyCObject_Check(descr)) { if (PyCObject_Check(descr)) {
@@ -192,8 +205,7 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr)
} else if (descr->ob_type->tp_descr_get) { } else if (descr->ob_type->tp_descr_get) {
return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy);
} else { } else {
fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)"); return NULL;
return descr;
} }
/* end py_getattro_up copy */ /* end py_getattro_up copy */
} }

View File

@@ -114,6 +114,9 @@ typedef struct {
// This defines the py_getattro_up macro // This defines the py_getattro_up macro
// which allows attribute and method calls // which allows attribute and method calls
// to be properly passed up the hierarchy. // to be properly passed up the hierarchy.
//
// Note, PyDict_GetItem() WONT set an exception!
// let the py_base_getattro function do this.
#define py_getattro_up(Parent) \ #define py_getattro_up(Parent) \
\ \
@@ -125,14 +128,11 @@ typedef struct {
} else if (descr->ob_type->tp_descr_get) { \ } else if (descr->ob_type->tp_descr_get) { \
return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \ return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \
} else { \ } else { \
fprintf(stderr, "unknown attribute type"); \ return NULL; \
return descr; \
} \ } \
} else { \ } else { \
PyErr_Clear(); \
return Parent::py_getattro(attr); \ return Parent::py_getattro(attr); \
} \ }
return NULL;
#define py_getattro_dict_up(Parent) \ #define py_getattro_dict_up(Parent) \
return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict); return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict);

View File

@@ -1655,7 +1655,7 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE
PyObject *meshes= PyList_New(self->m_meshes.size()); PyObject *meshes= PyList_New(self->m_meshes.size());
int i; int i;
for(i=0; i < self->m_meshes.size(); i++) for(i=0; i < (int)self->m_meshes.size(); i++)
{ {
KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]); KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
PyList_SET_ITEM(meshes, i, meshproxy->GetProxy()); PyList_SET_ITEM(meshes, i, meshproxy->GetProxy());