[Bf-python] Little error with 228c

Stephen Swaney sswaney at swbell.net
Mon Sep 29 10:49:52 CEST 2003


Manuel Bastioni wrote:
> 
> This code work under Blender 228a:
> 
> newBaseObj.name = "Base"
> 
> but using 228c I've this error:
> 
>   File "MorphFiles.py", line 303, in build
> AttributeError: expected a String as argument

The problem we have here comes from the way we use
the our setattrfunc to call methods to set attributes.
This is basically an excellent idea because the setXXX
methods do range checking and clamping and other nify things.

The catch is that the setatterfunc takes a single object
and the setXXX() methods take a tuple.  An equivalent way
to say this is the setattrfunc is of type PyCFunction and
the methods are of type PyMethodDef.

Because of the differing function types, we have to change
the setattrfunc's value param into a tuple before we pass it
into a setXXX method.

I made a 'minor' change to Object.c to deal with this.  Since
some of the attributes are set directly on the blender object
and some are set via setXXX methods and need some ref counting,
I did a little refactoring and separated them into two groups.
I *think* I got the ref count stuff correct.

A patch is attached.
-- 
Stephen Swaney			
sswaney at swbell.net
-------------- next part --------------
Index: Object.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/Object.c,v
retrieving revision 1.42
diff -u -r1.42 Object.c
--- Object.c	23 Sep 2003 03:02:54 -0000	1.42
+++ Object.c	29 Sep 2003 08:24:37 -0000
@@ -419,7 +419,7 @@
     PyObject        * list;
     Base            * base_iter;
 
-    printf ("In Object_GetSelected()\n");
+   /*  printf ("In Object_GetSelected()\n"); */
 
     list = PyList_New (0);
     if ((G.scene->basact) &&
@@ -1020,7 +1020,7 @@
     float   dloc2;
     float   dloc3;
 
-    if (!PyArg_ParseTuple (args, "fff", &dloc1, &dloc2, &dloc3))
+    if (!PyArg_ParseTuple (args, "(fff)", &dloc1, &dloc2, &dloc3))
     {
         return (PythonReturnErrorObject (PyExc_AttributeError,
                 "expected three float arguments"));
@@ -1070,10 +1070,10 @@
     float   rot2;
     float   rot3;
 
-    if (!PyArg_ParseTuple (args, "fff", &rot1, &rot2, &rot3))
+    if (!PyArg_ParseTuple (args, "(fff)", &rot1, &rot2, &rot3))
     {
         return (PythonReturnErrorObject (PyExc_AttributeError,
-                "expected three float arguments"));
+                "expected tuple with three floats "));
     }
 
     self->object->rot[0] = rot1;
@@ -1090,7 +1090,7 @@
     float   loc2;
     float   loc3;
 
-    if (!PyArg_ParseTuple (args, "fff", &loc1, &loc2, &loc3))
+    if (!PyArg_ParseTuple (args, "(fff)", &loc1, &loc2, &loc3))
     {
         return (PythonReturnErrorObject (PyExc_AttributeError,
                 "expected three float arguments"));
@@ -1456,163 +1456,219 @@
 {
     struct Object    * object;
     struct Ika      * ika;
+    PyObject * value_tpl;
+    PyObject *error;
+
 
+    /* 
+     * first we process attrs that are set directly on our object 
+     * and can use the PyArg_Parse style 
+     */
+
+    /* get a reference to our underlying blender object */
     object = obj->object;
+
     if (StringEqual (name, "LocX"))
-        return (!PyArg_Parse (value, "f", &(object->loc[0])));
+      return (!PyArg_Parse (value, "f", &(object->loc[0])));
+    
     if (StringEqual (name, "LocY"))
-        return (!PyArg_Parse (value, "f", &(object->loc[1])));
+      return (!PyArg_Parse (value, "f", &(object->loc[1])));
+    
     if (StringEqual (name, "LocZ"))
-        return (!PyArg_Parse (value, "f", &(object->loc[2])));
-    if (StringEqual (name, "loc"))
-    {
-        if (Object_setLocation (obj, value) != Py_None)
-            return (-1);
-        else
-            return (0);
-    }
+      return (!PyArg_Parse (value, "f", &(object->loc[2])));
+    
     if (StringEqual (name, "dLocX"))
-        return (!PyArg_Parse (value, "f", &(object->dloc[0])));
+      return (!PyArg_Parse (value, "f", &(object->dloc[0])));
+
     if (StringEqual (name, "dLocY"))
-        return (!PyArg_Parse (value, "f", &(object->dloc[1])));
+      return (!PyArg_Parse (value, "f", &(object->dloc[1])));
+
     if (StringEqual (name, "dLocZ"))
-        return (!PyArg_Parse (value, "f", &(object->dloc[2])));
-    if (StringEqual (name, "dloc"))
-    {
-        if (Object_setDeltaLocation (obj, value) != Py_None)
-            return (-1);
-        else
-            return (0);
-    }
+      return (!PyArg_Parse (value, "f", &(object->dloc[2])));
+
     if (StringEqual (name, "RotX"))
-        return (!PyArg_Parse (value, "f", &(object->rot[0])));
+      return (!PyArg_Parse (value, "f", &(object->rot[0])));
+
     if (StringEqual (name, "RotY"))
-        return (!PyArg_Parse (value, "f", &(object->rot[1])));
+      return (!PyArg_Parse (value, "f", &(object->rot[1])));
+
     if (StringEqual (name, "RotZ"))
-        return (!PyArg_Parse (value, "f", &(object->rot[2])));
-    if (StringEqual (name, "rot"))
-    {
-        if (Object_setEuler (obj, value) != Py_None)
-            return (-1);
-        else
-            return (0);
-    }
+      return (!PyArg_Parse (value, "f", &(object->rot[2])));
+
     if (StringEqual (name, "dRotX"))
-        return (!PyArg_Parse (value, "f", &(object->drot[0])));
+      return (!PyArg_Parse (value, "f", &(object->drot[0])));
+
     if (StringEqual (name, "dRotY"))
-        return (!PyArg_Parse (value, "f", &(object->drot[1])));
+      return (!PyArg_Parse (value, "f", &(object->drot[1])));
+
     if (StringEqual (name, "dRotZ"))
-        return (!PyArg_Parse (value, "f", &(object->drot[2])));
+      return (!PyArg_Parse (value, "f", &(object->drot[2])));
+
     if (StringEqual (name, "drot"))
-        return (!PyArg_Parse (value, "fff", &(object->drot[0]),
-                              &(object->drot[1]), &(object->drot[2])));
+      return (!PyArg_Parse (value, "fff", &(object->drot[0]),
+			    &(object->drot[1]), &(object->drot[2])));
+
     if (StringEqual (name, "SizeX"))
-        return (!PyArg_Parse (value, "f", &(object->size[0])));
+      return (!PyArg_Parse (value, "f", &(object->size[0])));
+
     if (StringEqual (name, "SizeY"))
-        return (!PyArg_Parse (value, "f", &(object->size[1])));
+      return (!PyArg_Parse (value, "f", &(object->size[1])));
+
     if (StringEqual (name, "SizeZ"))
-        return (!PyArg_Parse (value, "f", &(object->size[2])));
+      return (!PyArg_Parse (value, "f", &(object->size[2])));
+
     if (StringEqual (name, "size"))
-        return (!PyArg_Parse (value, "fff", &(object->size[0]),
-                              &(object->size[1]), &(object->size[2])));
+      return (!PyArg_Parse (value, "fff", &(object->size[0]),
+			    &(object->size[1]), &(object->size[2])));
     if (StringEqual (name, "dSizeX"))
-        return (!PyArg_Parse (value, "f", &(object->dsize[0])));
+      return (!PyArg_Parse (value, "f", &(object->dsize[0])));
+
     if (StringEqual (name, "dSizeY"))
-        return (!PyArg_Parse (value, "f", &(object->dsize[1])));
+      return (!PyArg_Parse (value, "f", &(object->dsize[1])));
+
     if (StringEqual (name, "dSizeZ"))
-        return (!PyArg_Parse (value, "f", &(object->dsize[2])));
+      return (!PyArg_Parse (value, "f", &(object->dsize[2])));
+
     if (StringEqual (name, "dsize"))
-        return (!PyArg_Parse (value, "fff", &(object->dsize[0]),
-                              &(object->dsize[1]), &(object->dsize[2])));
+      return (!PyArg_Parse (value, "fff", &(object->dsize[0]),
+			    &(object->dsize[1]), &(object->dsize[2])));
+
     if (strncmp (name,"Eff", 3) == 0)
-    {
+      {
         if ( (object->type == OB_IKA) && (object->data != NULL) )
-        {
+	  {
             ika = object->data;
             switch (name[3])
-            {
-                case 'X':
-                    return (!PyArg_Parse (value, "f", &(ika->effg[0])));
-                case 'Y':
-                    return (!PyArg_Parse (value, "f", &(ika->effg[1])));
-                case 'Z':
-                    return (!PyArg_Parse (value, "f", &(ika->effg[2])));
-                default:
-                    /* Do we need to display a sensible error message here? */
-                    return (0);
-            }
-        }
+	      {
+	      case 'X':
+		return (!PyArg_Parse (value, "f", &(ika->effg[0])));
+	      case 'Y':
+		return (!PyArg_Parse (value, "f", &(ika->effg[1])));
+	      case 'Z':
+		return (!PyArg_Parse (value, "f", &(ika->effg[2])));
+	      default:
+		/* Do we need to display a sensible error message here? */
+		return (0);
+	      }
+	  }
         return (0);
-    }
+      }
+
     if (StringEqual (name, "Layer"))
-        return (!PyArg_Parse (value, "i", &(object->lay)));
-    if (StringEqual (name, "parent"))
-    {
+      return (!PyArg_Parse (value, "i", &(object->lay)));
+
+    if (StringEqual (name, "colbits"))
+      return (!PyArg_Parse (value, "h", &(object->colbits)));
+
+    /* handle  attempts to set unsetable attrs */
+
+   if (StringEqual (name, "parent"))
+      {
         /* This is not allowed. */
         PythonReturnErrorObject (PyExc_AttributeError,
-                    "Setting the parent is not allowed.");
+				 "Setting the parent is not allowed.");
         return (0);
-    }
+      }
+
     if (StringEqual (name, "track"))
-    {
+      {
         /* This is not allowed. */
         PythonReturnErrorObject (PyExc_AttributeError,
-                    "Setting the track is not allowed.");
+				 "Setting the track is not allowed.");
         return (0);
-    }
+      }
+
     if (StringEqual (name, "data"))
-    {
+      {
         /* This is not allowed. */
         PythonReturnErrorObject (PyExc_AttributeError,
-                    "Setting the data is not allowed.");
+				 "Setting the data is not allowed.");
         return (0);
-    }
+      }
+
     if (StringEqual (name, "ipo"))
-    {
+      {
         /* This is not allowed. */
         PythonReturnErrorObject (PyExc_AttributeError,
-                    "Setting the ipo is not allowed.");
+				 "Setting the ipo is not allowed.");
         return (0);
-    }
+      }
+
     if (StringEqual (name, "mat"))
-    {
+      {
         /* This is not allowed. */
         PythonReturnErrorObject (PyExc_AttributeError,
-                    "Setting the matrix is not allowed.");
+				 "Setting the matrix is not allowed.");
         return (0);
-    }
+      }
+
     if (StringEqual (name, "matrix"))
-    {
+      {
         /* This is not allowed. */
         PythonReturnErrorObject (PyExc_AttributeError,
-                    "Setting the matrix is not allowed.");
+				 "Setting the matrix is not allowed.");
         return (0);
-    }
-    if (StringEqual (name, "colbits"))
-        return (!PyArg_Parse (value, "h", &(object->colbits)));
-    if (StringEqual (name, "drawType"))
-    {
-        if (Object_setDrawType (obj, value) != Py_None)
-            return (-1);
-        else
-            return (0);
-    }
-    if (StringEqual (name, "drawMode"))
-    {
-        if (Object_setDrawMode (obj, value) != Py_None)
-            return (-1);
-        else
-            return (0);
-    }
-    if (StringEqual (name, "name"))
-    {
-        if (Object_setName (obj, value) != Py_None)
-            return (-1);
-        else
-            return (0);
-    }
+      }
+
+    /*
+     * Now we handle attrs that are process by setXXXX() methods
+     * The value param passed in here is a single PyObject*,
+     * so it gets unpacked with PyArg_Parse.
+     * It is not a tuple, unlike the arguments passed to
+     * the funcs in our Method tables.  Methods are of type
+     * PyMethodDef and expect their second arg to be a tuple.
+     * therefore, we  need to take our single value arg and 
+     * wrap it up  as a tuple so we can pass it to a method
+     */
+
+    /* make tuple from value */
+    value_tpl = Py_BuildValue( "(O)", value );
+
+    /* bail out if BuildValue failed */
+    if( !value_tpl )
+      return EXPP_ReturnIntError( PyExc_MemoryError,
+				 "Object_setAttr: can't create tuple");
+
+    if (StringEqual (name, "loc"))
+      {
+	error = Object_setLocation (obj, value_tpl);
+      }
+    else if (StringEqual (name, "dloc"))
+      {
+        error = Object_setDeltaLocation (obj, value_tpl);
+      }
+    else if (StringEqual (name, "rot"))
+      {
+	error = Object_setEuler (obj, value_tpl);
+      }
+    else if (StringEqual (name, "drawType"))
+      {
+	error = Object_setDrawType (obj, value_tpl);
+      }
+    else if (StringEqual (name, "drawMode"))
+      {
+        error = Object_setDrawMode (obj, value_tpl);
+      }
+    else if (StringEqual (name, "name"))
+      {
+        error = Object_setName (obj, value_tpl );
+      }
+    else /* no such attribute */
+      {
+	Py_DECREF( value_tpl );
+	return  (EXPP_ReturnIntError (PyExc_KeyError,
+				      "attribute not found"));
+      }
 
-    printf ("Unknown variable.\n");
+    /* now we clean up and report errors */
+    Py_DECREF( value_tpl );
+    
+    /* bad stuff happened */
+    if( error != Py_None ) 
+      return( -1 );
+    
+    /* A-OK! */
+    Py_DECREF( Py_None );
     return (0);
 }
 


More information about the Bf-python mailing list