copy of docs from 2.4x for python modules that have been kept
[blender.git] / source / blender / python / generic / IDProp.c
index 3ec3f30bb0f3bb3d6c9088e5be2889f39042b242..b3679c8f4a2b5e7d7ea8189cb292a3f7c88b4787 100644 (file)
@@ -64,11 +64,6 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
                        /*blegh*/
                        {
                                BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &IDGroup_Type);
-                               if (!group) {
-                                       PyErr_SetString( PyExc_RuntimeError, "PyObject_New() failed" );
-                                       return NULL;
-                               }
-
                                group->id = id;
                                group->prop = prop;
                                return (PyObject*) group;
@@ -76,10 +71,6 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
                case IDP_ARRAY:
                        {
                                BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &IDArray_Type);
-                               if (!array) {
-                                       PyErr_SetString( PyExc_RuntimeError, "PyObject_New() failed" );
-                                       return NULL;
-                               }
                                array->id = id;
                                array->prop = prop;
                                return (PyObject*) array;
@@ -307,50 +298,51 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
        return NULL;
 }
 
-static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject *val)
+int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val)
 {
-       char *err;
-
-       if (self->prop->type  != IDP_GROUP) {
+       if (prop->type  != IDP_GROUP) {
                PyErr_SetString( PyExc_TypeError, "unsubscriptable object");
                return -1;
        }
 
-       if (!PyUnicode_Check(key)) {
-               PyErr_SetString( PyExc_TypeError, "only strings are allowed as subgroup keys" );
-               return -1;
-       }
-
-       if (val == NULL) {
-               IDProperty *pkey = IDP_GetPropertyFromGroup(self->prop, _PyUnicode_AsString(key));
+       if (val == NULL) { /* del idprop[key] */
+               IDProperty *pkey = IDP_GetPropertyFromGroup(prop, _PyUnicode_AsString(key));
                if (pkey) {
-                       IDP_RemFromGroup(self->prop, pkey);
+                       IDP_RemFromGroup(prop, pkey);
                        IDP_FreeProperty(pkey);
                        MEM_freeN(pkey);
                        return 0;
                } else {
-                       PyErr_SetString( PyExc_RuntimeError, "property not found in group" );
+                       PyErr_SetString( PyExc_KeyError, "property not found in group" );
                        return -1;
                }
        }
+       else {
+               char *err;
 
-       err = BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), self->prop, val);
-       if (err) {
-               PyErr_SetString( PyExc_RuntimeError, err );
-               return -1;
+               if (!PyUnicode_Check(key)) {
+                       PyErr_SetString( PyExc_TypeError, "only strings are allowed as subgroup keys" );
+                       return -1;
+               }
+
+               err = BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, val);
+               if (err) {
+                       PyErr_SetString( PyExc_KeyError, err );
+                       return -1;
+               }
+
+               return 0;
        }
+}
 
-       return 0;
+static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject *val)
+{
+       return BPy_Wrap_SetMapItem(self->prop, key, val);
 }
 
 static PyObject *BPy_IDGroup_SpawnIterator(BPy_IDProperty *self)
 {
        BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
-
-       if (!iter) {
-               PyErr_SetString( PyExc_RuntimeError, "PyObject_New() failed" );
-               return NULL;
-       }
        iter->group = self;
        iter->mode = IDPROP_ITER_KEYS;
        iter->cur = self->prop->data.group.first;
@@ -385,12 +377,13 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
 
                        for (i=0; i<prop->len; i++) {
                                if (prop->subtype == IDP_FLOAT) {
-                                               PyList_SetItem(seq, i,
+                                       PyList_SET_ITEM(seq, i,
                                                PyFloat_FromDouble(((float*)prop->data.pointer)[i]));
                                } else if (prop->subtype == IDP_DOUBLE) {
-                                               PyList_SetItem(seq, i,
+                                       PyList_SET_ITEM(seq, i,
                                                PyFloat_FromDouble(((double*)prop->data.pointer)[i]));
-                               } else  { PyList_SetItem(seq, i,
+                               } else  {
+                                       PyList_SET_ITEM(seq, i,
                                                  PyLong_FromLong(((int*)prop->data.pointer)[i]));
                                }
                        }
@@ -457,12 +450,6 @@ static PyObject *BPy_IDGroup_Pop(BPy_IDProperty *self, PyObject *value)
 static PyObject *BPy_IDGroup_IterItems(BPy_IDProperty *self)
 {
        BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
-
-       if (!iter) {
-               PyErr_SetString( PyExc_RuntimeError, "PyObject_New() failed" );
-               return NULL;
-       }
-
        iter->group = self;
        iter->mode = IDPROP_ITER_ITEMS;
        iter->cur = self->prop->data.group.first;
@@ -470,79 +457,101 @@ static PyObject *BPy_IDGroup_IterItems(BPy_IDProperty *self)
        return (PyObject*) iter;
 }
 
-static PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self)
+/* utility function */
+static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len)
 {
-       PyObject *seq = PyList_New(self->prop->len);
-       IDProperty *loop;
-       int i, j;
+       int j;
 
-       if (!seq) {
-               PyErr_SetString( PyExc_RuntimeError, "PyList_New() failed" );
-               return NULL;
-       }
+       printf("ID Property Error found and corrected in BPy_IDGroup_GetKeys/Values/Items!\n");
 
-       for (i=0, loop=self->prop->data.group.first; loop; loop=loop->next, i++)
-               PyList_SetItem(seq, i, PyUnicode_FromString(loop->name));
-
-       if (i != self->prop->len) {
-               printf("ID Property Error found and corrected in BPy_IDGroup_GetKeys!\n");
+       /*fill rest of list with valid references to None*/
+       for (j=len; j<prop->len; j++) {
+               Py_INCREF(Py_None);
+               PyList_SET_ITEM(seq, j, Py_None);
+       }
 
-               /*fill rest of list with valid references to None*/
-               for (j=i; j<self->prop->len; j++) {
-                       Py_INCREF(Py_None);
-                       PyList_SetItem(seq, j, Py_None);
-               }
+       /*set correct group length*/
+       prop->len = len;
+}
 
-               /*set correct group length*/
-               self->prop->len = i;
+PyObject *BPy_Wrap_GetKeys(IDProperty *prop)
+{
+       PyObject *seq = PyList_New(prop->len);
+       IDProperty *loop;
+       int i;
 
-               /*free the list*/
-               Py_DECREF(seq);
+       for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++)
+               PyList_SET_ITEM(seq, i, PyUnicode_FromString(loop->name));
 
+       if (i != prop->len) {
+               BPy_IDGroup_CorrectListLen(prop, seq, i);
+               Py_DECREF(seq); /*free the list*/
                /*call self again*/
-               return BPy_IDGroup_GetKeys(self);
+               return BPy_Wrap_GetKeys(prop);
        }
 
        return seq;
 }
 
-static PyObject *BPy_IDGroup_GetValues(BPy_IDProperty *self)
+PyObject *BPy_Wrap_GetValues(ID *id, IDProperty *prop)
 {
-       PyObject *seq = PyList_New(self->prop->len);
+       PyObject *seq = PyList_New(prop->len);
        IDProperty *loop;
-       int i, j;
+       int i;
 
-       if (!seq) {
-               PyErr_SetString( PyExc_RuntimeError, "PyList_New() failed" );
-               return NULL;
+       for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) {
+               PyList_SET_ITEM(seq, i, BPy_IDGroup_WrapData(id, loop));
        }
 
-       for (i=0, loop=self->prop->data.group.first; loop; loop=loop->next, i++) {
-               PyList_SetItem(seq, i, BPy_IDGroup_WrapData(self->id, loop));
+       if (i != prop->len) {
+               BPy_IDGroup_CorrectListLen(prop, seq, i);
+               Py_DECREF(seq); /*free the list*/
+               /*call self again*/
+               return BPy_Wrap_GetValues(id, prop);
        }
 
-       if (i != self->prop->len) {
-               printf("ID Property Error found and corrected in BPy_IDGroup_GetValues!\n");
-
-               /*fill rest of list with valid references to None*/
-               for (j=i; j<self->prop->len; j++) {
-                       Py_INCREF(Py_None);
-                       PyList_SetItem(seq, j, Py_None);
-               }
+       return seq;
+}
 
-               /*set correct group length*/
-               self->prop->len = i;
+PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop)
+{
+       PyObject *seq = PyList_New(prop->len);
+       IDProperty *loop;
+       int i;
 
-               /*free the old list*/
-               Py_DECREF(seq);
+       for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) {
+               PyObject *item= PyTuple_New(2);
+               PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(loop->name));
+               PyTuple_SET_ITEM(item, 1, BPy_IDGroup_WrapData(id, loop));
+               PyList_SET_ITEM(seq, i, item);
+       }
 
+       if (i != prop->len) {
+               BPy_IDGroup_CorrectListLen(prop, seq, i);
+               Py_DECREF(seq); /*free the list*/
                /*call self again*/
-               return BPy_IDGroup_GetValues(self);
+               return BPy_Wrap_GetItems(id, prop);
        }
 
        return seq;
 }
 
+
+static PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self)
+{
+       return BPy_Wrap_GetKeys(self->prop);
+}
+
+static PyObject *BPy_IDGroup_GetValues(BPy_IDProperty *self)
+{
+       return BPy_Wrap_GetValues(self->id, self->prop);
+}
+
+static PyObject *BPy_IDGroup_GetItems(BPy_IDProperty *self)
+{
+       return BPy_Wrap_GetItems(self->id, self->prop);
+}
+
 static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value)
 {
        char *name = _PyUnicode_AsString(value);
@@ -578,6 +587,28 @@ static PyObject *BPy_IDGroup_ConvertToPy(BPy_IDProperty *self)
        return BPy_IDGroup_MapDataToPy(self->prop);
 }
 
+
+/* Matches python dict.get(key, [default]) */
+PyObject* BPy_IDGroup_Get(BPy_IDProperty *self, PyObject *args)
+{
+       IDProperty *idprop;
+       char *key;
+       PyObject* def = Py_None;
+
+       if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
+               return NULL;
+
+       idprop= IDP_GetPropertyFromGroup(self->prop, key);
+       if (idprop) {
+               PyObject* pyobj = BPy_IDGroup_WrapData(self->id, idprop);
+               if (pyobj)
+                       return pyobj;
+       }
+
+       Py_INCREF(def);
+       return def;
+}
+
 static struct PyMethodDef BPy_IDGroup_methods[] = {
        {"pop", (PyCFunction)BPy_IDGroup_Pop, METH_O,
                "pop an item from the group; raises KeyError if the item doesn't exist."},
@@ -587,8 +618,12 @@ static struct PyMethodDef BPy_IDGroup_methods[] = {
                "get the keys associated with this group as a list of strings."},
        {"values", (PyCFunction)BPy_IDGroup_GetValues, METH_NOARGS,
                "get the values associated with this group."},
+       {"items", (PyCFunction)BPy_IDGroup_GetItems, METH_NOARGS,
+               "get the items associated with this group."},
        {"update", (PyCFunction)BPy_IDGroup_Update, METH_O,
                "updates the values in the group with the values of another or a dict."},
+       {"get", (PyCFunction)BPy_IDGroup_Get, METH_VARARGS,
+               "idprop.get(k[,d]) -> idprop[k] if k in idprop, else d.  d defaults to None."},
        {"convert_to_pyobject", (PyCFunction)BPy_IDGroup_ConvertToPy, METH_NOARGS,
                "return a purely python version of the group."},
        {0, NULL, 0, NULL}
@@ -678,12 +713,6 @@ PyTypeObject IDGroup_Type = {
 PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent)
 {
        BPy_IDProperty *wrap = PyObject_New(BPy_IDProperty, &IDGroup_Type);
-
-       if (!wrap) {
-               PyErr_SetString( PyExc_RuntimeError, "PyObject_New() failed" );
-               return NULL;
-       }
-
        wrap->prop = prop;
        wrap->parent = parent;
        wrap->id = id;
@@ -722,6 +751,17 @@ static PyGetSetDef BPy_IDArray_getseters[] = {
        {NULL, NULL, NULL, NULL, NULL},
 };
 
+static PyObject *BPy_IDArray_ConvertToPy(BPy_IDArray *self)
+{
+       return BPy_IDGroup_MapDataToPy(self->prop);
+}
+
+static PyMethodDef BPy_IDArray_methods[] = {
+       {"convert_to_pyobject", (PyCFunction)BPy_IDArray_ConvertToPy, METH_NOARGS,
+               "return a purely python version of the group."},
+       {0, NULL, 0, NULL}
+};
+
 static int BPy_IDArray_Len(BPy_IDArray *self)
 {
        return self->prop->len;
@@ -862,7 +902,7 @@ PyTypeObject IDArray_Type = {
        NULL,                       /* iternextfunc tp_iternext; */
 
   /*** Attribute descriptor and subclassing stuff ***/
-       NULL,                       /* struct PyMethodDef *tp_methods; */
+       BPy_IDArray_methods,            /* struct PyMethodDef *tp_methods; */
        NULL,                       /* struct PyMemberDef *tp_members; */
        BPy_IDArray_getseters,       /* struct PyGetSetDef *tp_getset; */
        NULL,                       /* struct _typeobject *tp_base; */
@@ -902,16 +942,15 @@ static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
 static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
 {
        IDProperty *cur=NULL;
-       PyObject *tmpval;
        PyObject *ret;
 
        if (self->cur) {
                cur = self->cur;
                self->cur = self->cur->next;
                if (self->mode == IDPROP_ITER_ITEMS) {
-                       tmpval = BPy_IDGroup_WrapData(self->group->id, cur);
-                       ret = Py_BuildValue("[s, O]", cur->name, tmpval);
-                       Py_DECREF(tmpval);
+                       ret = PyTuple_New(2);
+                       PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(cur->name));
+                       PyTuple_SET_ITEM(ret, 1, BPy_IDGroup_WrapData(self->group->id, cur));
                        return ret;
                } else {
                        return PyUnicode_FromString(cur->name);