BGE Python API
authorCampbell Barton <ideasman42@gmail.com>
Wed, 22 Apr 2009 09:47:57 +0000 (09:47 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 22 Apr 2009 09:47:57 +0000 (09:47 +0000)
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.

source/gameengine/Expressions/PyObjectPlus.cpp
source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/Ketsji/KX_GameObject.cpp

index 96753d56d944a2f8f7743535ee4c39204cd438bf..30495fc2a45a222df90ac409eb8cb0e0cf7ed9e2 100644 (file)
@@ -146,9 +146,23 @@ PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr)
        
        PyObject *ret= self_plus->py_getattro(attr);
        
-       if(ret==NULL && (strcmp(PyString_AsString(attr), "__dict__")==0))
-               ret= self_plus->py_getattro_dict();
-       
+       /* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */
+       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;
 }
 
@@ -183,8 +197,7 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr)
 {
        PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
        if (descr == NULL) {
-               PyErr_Format(PyExc_AttributeError, "attribute \"%s\" not found", PyString_AsString(attr));
-               return NULL;
+               return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */
        } else {
                /* Copied from py_getattro_up */
                if (PyCObject_Check(descr)) {
@@ -192,8 +205,7 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr)
                } else if (descr->ob_type->tp_descr_get) {
                        return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy);
                } else {
-                       fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)");
-                       return descr;
+                       return NULL;
                }
                /* end py_getattro_up copy */
        }
index b0ddfa04e3284eeb2444c1db43916935a1f6a582..a3b3952a6d1bdc60e15baa5c61af2070a7065bd0 100644 (file)
@@ -114,6 +114,9 @@ typedef struct {
                                                                // This defines the py_getattro_up macro
                                                                // which allows attribute and method calls
                                                                // 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) \
        \
@@ -125,14 +128,11 @@ typedef struct {
                } else if (descr->ob_type->tp_descr_get) { \
                        return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \
                } else { \
-                       fprintf(stderr, "unknown attribute type"); \
-                       return descr; \
+                       return NULL; \
                } \
        } else { \
-               PyErr_Clear(); \
                return Parent::py_getattro(attr); \
-       } \
-       return NULL;
+       }
 
 #define py_getattro_dict_up(Parent) \
        return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict);
index 1f4c9c2e9d5009c49f1e84738f35d578455f17eb..eb20cfa11311cf4c01265c289c75e70fe3cae0d3 100644 (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());
        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]);
                PyList_SET_ITEM(meshes, i, meshproxy->GetProxy());