|
Blender
V2.59
|
00001 /* 00002 * $Id: IDProp.c 37581 2011-06-17 05:56:17Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * 00021 * Contributor(s): Joseph Eagar, Campbell Barton 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <Python.h> 00032 00033 #include "IDProp.h" 00034 #include "MEM_guardedalloc.h" 00035 00036 #include "BLI_string.h" 00037 #include "BLI_utildefines.h" 00038 00039 #include "BKE_idprop.h" 00040 00041 00042 #define USE_STRING_COERCE 00043 00044 #ifdef USE_STRING_COERCE 00045 #include "py_capi_utils.h" 00046 #endif 00047 00048 extern PyTypeObject BPy_IDArray_Type; 00049 extern PyTypeObject BPy_IDGroup_Iter_Type; 00050 extern PyTypeObject BPy_IDGroup_Type; 00051 00052 /*********************** ID Property Main Wrapper Stuff ***************/ 00053 00054 /* use for both array and group */ 00055 static long BPy_IDGroup_hash(BPy_IDProperty *self) 00056 { 00057 return _Py_HashPointer(self->prop); 00058 } 00059 00060 static PyObject *BPy_IDGroup_repr(BPy_IDProperty *self) 00061 { 00062 return PyUnicode_FromFormat( "<bpy id property from \"%s\">", self->id->name); 00063 } 00064 00065 PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop ) 00066 { 00067 switch ( prop->type ) { 00068 case IDP_STRING: 00069 #ifdef USE_STRING_COERCE 00070 return PyC_UnicodeFromByte(IDP_Array(prop)); 00071 #else 00072 return PyUnicode_FromString(IDP_Array(prop)); 00073 #endif 00074 case IDP_INT: 00075 return PyLong_FromLong( (long)prop->data.val ); 00076 case IDP_FLOAT: 00077 return PyFloat_FromDouble( (double)(*(float*)(&prop->data.val)) ); 00078 case IDP_DOUBLE: 00079 return PyFloat_FromDouble( (*(double*)(&prop->data.val)) ); 00080 case IDP_GROUP: 00081 /*blegh*/ 00082 { 00083 BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type); 00084 group->id = id; 00085 group->prop = prop; 00086 return (PyObject*) group; 00087 } 00088 case IDP_ARRAY: 00089 { 00090 BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &BPy_IDArray_Type); 00091 array->id = id; 00092 array->prop = prop; 00093 return (PyObject*) array; 00094 } 00095 case IDP_IDPARRAY: /* this could be better a internal type */ 00096 { 00097 PyObject *seq = PyList_New(prop->len), *wrap; 00098 IDProperty *array= IDP_IDPArray(prop); 00099 int i; 00100 00101 if (!seq) { 00102 PyErr_Format(PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len); 00103 return NULL; 00104 } 00105 00106 for (i=0; i<prop->len; i++) { 00107 wrap= BPy_IDGroup_WrapData(id, array++); 00108 00109 if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */ 00110 return NULL; 00111 00112 PyList_SET_ITEM(seq, i, wrap); 00113 } 00114 00115 return seq; 00116 } 00117 /* case IDP_IDPARRAY: TODO */ 00118 } 00119 Py_RETURN_NONE; 00120 } 00121 00122 #if 0 /* UNUSED, currenly assignment overwrites into new properties, rather than setting in-place */ 00123 static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject *value) 00124 { 00125 switch (prop->type) { 00126 case IDP_STRING: 00127 { 00128 char *st; 00129 if (!PyUnicode_Check(value)) { 00130 PyErr_SetString(PyExc_TypeError, "expected a string!"); 00131 return -1; 00132 } 00133 #ifdef USE_STRING_COERCE 00134 { 00135 int alloc_len; 00136 PyObject *value_coerce= NULL; 00137 00138 st= (char *)PyC_UnicodeAsByte(value, &value_coerce); 00139 alloc_len= strlen(st) + 1; 00140 00141 st = _PyUnicode_AsString(value); 00142 IDP_ResizeArray(prop, alloc_len); 00143 memcpy(IDP_Array(prop), st, alloc_len); 00144 Py_XDECREF(value_coerce); 00145 } 00146 #else 00147 st = _PyUnicode_AsString(value); 00148 IDP_ResizeArray(prop, strlen(st)+1); 00149 strcpy(IDP_Array(prop), st); 00150 #endif 00151 00152 return 0; 00153 } 00154 00155 case IDP_INT: 00156 { 00157 int ivalue= PyLong_AsSsize_t(value); 00158 if (ivalue==-1 && PyErr_Occurred()) { 00159 PyErr_SetString(PyExc_TypeError, "expected an int type"); 00160 return -1; 00161 } 00162 prop->data.val = ivalue; 00163 break; 00164 } 00165 case IDP_FLOAT: 00166 { 00167 float fvalue= (float)PyFloat_AsDouble(value); 00168 if (fvalue==-1 && PyErr_Occurred()) { 00169 PyErr_SetString(PyExc_TypeError, "expected a float"); 00170 return -1; 00171 } 00172 *(float*)&self->prop->data.val = fvalue; 00173 break; 00174 } 00175 case IDP_DOUBLE: 00176 { 00177 double dvalue= PyFloat_AsDouble(value); 00178 if (dvalue==-1 && PyErr_Occurred()) { 00179 PyErr_SetString(PyExc_TypeError, "expected a float"); 00180 return -1; 00181 } 00182 *(double*)&self->prop->data.val = dvalue; 00183 break; 00184 } 00185 default: 00186 PyErr_SetString(PyExc_AttributeError, "attempt to set read-only attribute!"); 00187 return -1; 00188 } 00189 return 0; 00190 } 00191 #endif 00192 00193 static PyObject *BPy_IDGroup_GetName(BPy_IDProperty *self, void *UNUSED(closure)) 00194 { 00195 return PyUnicode_FromString(self->prop->name); 00196 } 00197 00198 static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUSED(closure)) 00199 { 00200 char *st; 00201 if (!PyUnicode_Check(value)) { 00202 PyErr_SetString(PyExc_TypeError, "expected a string!"); 00203 return -1; 00204 } 00205 00206 st = _PyUnicode_AsString(value); 00207 if (BLI_strnlen(st, MAX_IDPROP_NAME) == MAX_IDPROP_NAME) { 00208 PyErr_SetString(PyExc_TypeError, "string length cannot exceed 31 characters!"); 00209 return -1; 00210 } 00211 00212 BLI_strncpy(self->prop->name, st, sizeof(self->prop->name)); 00213 return 0; 00214 } 00215 00216 #if 0 00217 static PyObject *BPy_IDGroup_GetType(BPy_IDProperty *self) 00218 { 00219 return PyLong_FromSsize_t(self->prop->type); 00220 } 00221 #endif 00222 00223 static PyGetSetDef BPy_IDGroup_getseters[] = { 00224 {(char *)"name", (getter)BPy_IDGroup_GetName, (setter)BPy_IDGroup_SetName, (char *)"The name of this Group.", NULL}, 00225 {NULL, NULL, NULL, NULL, NULL} 00226 }; 00227 00228 static Py_ssize_t BPy_IDGroup_Map_Len(BPy_IDProperty *self) 00229 { 00230 if (self->prop->type != IDP_GROUP) { 00231 PyErr_SetString(PyExc_TypeError, "len() of unsized object"); 00232 return -1; 00233 } 00234 00235 return self->prop->len; 00236 } 00237 00238 static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item) 00239 { 00240 IDProperty *idprop; 00241 char *name; 00242 00243 if (self->prop->type != IDP_GROUP) { 00244 PyErr_SetString(PyExc_TypeError, "unsubscriptable object"); 00245 return NULL; 00246 } 00247 00248 name= _PyUnicode_AsString(item); 00249 00250 if (name == NULL) { 00251 PyErr_SetString(PyExc_TypeError, "only strings are allowed as keys of ID properties"); 00252 return NULL; 00253 } 00254 00255 idprop= IDP_GetPropertyFromGroup(self->prop, name); 00256 00257 if(idprop==NULL) { 00258 PyErr_SetString(PyExc_KeyError, "key not in subgroup dict"); 00259 return NULL; 00260 } 00261 00262 return BPy_IDGroup_WrapData(self->id, idprop); 00263 00264 } 00265 00266 /*returns NULL on success, error string on failure*/ 00267 static int idp_sequence_type(PyObject *seq) 00268 { 00269 PyObject *item; 00270 int type= IDP_INT; 00271 00272 int i, len = PySequence_Size(seq); 00273 for (i=0; i < len; i++) { 00274 item = PySequence_GetItem(seq, i); 00275 if (PyFloat_Check(item)) { 00276 if(type == IDP_IDPARRAY) { /* mixed dict/int */ 00277 Py_DECREF(item); 00278 return -1; 00279 } 00280 type= IDP_DOUBLE; 00281 } 00282 else if (PyLong_Check(item)) { 00283 if(type == IDP_IDPARRAY) { /* mixed dict/int */ 00284 Py_DECREF(item); 00285 return -1; 00286 } 00287 } 00288 else if (PyMapping_Check(item)) { 00289 if(i != 0 && (type != IDP_IDPARRAY)) { /* mixed dict/int */ 00290 Py_DECREF(item); 00291 return -1; 00292 } 00293 type= IDP_IDPARRAY; 00294 } 00295 else { 00296 Py_XDECREF(item); 00297 return -1; 00298 } 00299 00300 Py_DECREF(item); 00301 } 00302 00303 return type; 00304 } 00305 00306 /* note: group can be a pointer array or a group */ 00307 const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *group, PyObject *ob) 00308 { 00309 IDProperty *prop = NULL; 00310 IDPropertyTemplate val = {0}; 00311 00312 if(strlen(name) >= sizeof(group->name)) 00313 return "the length of IDProperty names is limited to 31 characters"; 00314 00315 if (PyFloat_Check(ob)) { 00316 val.d = PyFloat_AsDouble(ob); 00317 prop = IDP_New(IDP_DOUBLE, val, name); 00318 } 00319 else if (PyLong_Check(ob)) { 00320 val.i = (int) PyLong_AsSsize_t(ob); 00321 prop = IDP_New(IDP_INT, val, name); 00322 } 00323 else if (PyUnicode_Check(ob)) { 00324 #ifdef USE_STRING_COERCE 00325 PyObject *value_coerce= NULL; 00326 val.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce); 00327 prop = IDP_New(IDP_STRING, val, name); 00328 Py_XDECREF(value_coerce); 00329 #else 00330 val.str = _PyUnicode_AsString(ob); 00331 prop = IDP_New(IDP_STRING, val, name); 00332 #endif 00333 } 00334 else if (PySequence_Check(ob)) { 00335 PyObject *item; 00336 int i; 00337 00338 if((val.array.type= idp_sequence_type(ob)) == -1) 00339 return "only floats, ints and dicts are allowed in ID property arrays"; 00340 00341 /*validate sequence and derive type. 00342 we assume IDP_INT unless we hit a float 00343 number; then we assume it's */ 00344 00345 val.array.len = PySequence_Size(ob); 00346 00347 switch(val.array.type) { 00348 case IDP_DOUBLE: 00349 prop = IDP_New(IDP_ARRAY, val, name); 00350 for (i=0; i<val.array.len; i++) { 00351 item = PySequence_GetItem(ob, i); 00352 ((double*)IDP_Array(prop))[i] = (float)PyFloat_AsDouble(item); 00353 Py_DECREF(item); 00354 } 00355 break; 00356 case IDP_INT: 00357 prop = IDP_New(IDP_ARRAY, val, name); 00358 for (i=0; i<val.array.len; i++) { 00359 item = PySequence_GetItem(ob, i); 00360 ((int*)IDP_Array(prop))[i] = (int)PyLong_AsSsize_t(item); 00361 Py_DECREF(item); 00362 } 00363 break; 00364 case IDP_IDPARRAY: 00365 prop= IDP_NewIDPArray(name); 00366 for (i=0; i<val.array.len; i++) { 00367 const char *error; 00368 item = PySequence_GetItem(ob, i); 00369 error= BPy_IDProperty_Map_ValidateAndCreate("", prop, item); 00370 Py_DECREF(item); 00371 00372 if(error) 00373 return error; 00374 } 00375 break; 00376 } 00377 } 00378 else if (PyMapping_Check(ob)) { 00379 PyObject *keys, *vals, *key, *pval; 00380 int i, len; 00381 /*yay! we get into recursive stuff now!*/ 00382 keys = PyMapping_Keys(ob); 00383 vals = PyMapping_Values(ob); 00384 00385 /*we allocate the group first; if we hit any invalid data, 00386 we can delete it easily enough.*/ 00387 prop = IDP_New(IDP_GROUP, val, name); 00388 len = PyMapping_Length(ob); 00389 for (i=0; i<len; i++) { 00390 key = PySequence_GetItem(keys, i); 00391 pval = PySequence_GetItem(vals, i); 00392 if (!PyUnicode_Check(key)) { 00393 IDP_FreeProperty(prop); 00394 MEM_freeN(prop); 00395 Py_XDECREF(keys); 00396 Py_XDECREF(vals); 00397 Py_XDECREF(key); 00398 Py_XDECREF(pval); 00399 return "invalid element in subgroup dict template!"; 00400 } 00401 if (BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, pval)) { 00402 IDP_FreeProperty(prop); 00403 MEM_freeN(prop); 00404 Py_XDECREF(keys); 00405 Py_XDECREF(vals); 00406 Py_XDECREF(key); 00407 Py_XDECREF(pval); 00408 return "invalid element in subgroup dict template!"; 00409 } 00410 Py_XDECREF(key); 00411 Py_XDECREF(pval); 00412 } 00413 Py_XDECREF(keys); 00414 Py_XDECREF(vals); 00415 } 00416 else return "invalid property value"; 00417 00418 if(group->type==IDP_IDPARRAY) { 00419 IDP_AppendArray(group, prop); 00420 // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory 00421 MEM_freeN(prop); 00422 } 00423 else { 00424 IDP_ReplaceInGroup(group, prop); 00425 } 00426 00427 return NULL; 00428 } 00429 00430 int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val) 00431 { 00432 if (prop->type != IDP_GROUP) { 00433 PyErr_SetString(PyExc_TypeError, "unsubscriptable object"); 00434 return -1; 00435 } 00436 00437 if (val == NULL) { /* del idprop[key] */ 00438 IDProperty *pkey = IDP_GetPropertyFromGroup(prop, _PyUnicode_AsString(key)); 00439 if (pkey) { 00440 IDP_RemFromGroup(prop, pkey); 00441 IDP_FreeProperty(pkey); 00442 MEM_freeN(pkey); 00443 return 0; 00444 } 00445 else { 00446 PyErr_SetString(PyExc_KeyError, "property not found in group"); 00447 return -1; 00448 } 00449 } 00450 else { 00451 const char *err; 00452 00453 if (!PyUnicode_Check(key)) { 00454 PyErr_SetString(PyExc_TypeError, "only strings are allowed as subgroup keys"); 00455 return -1; 00456 } 00457 00458 err = BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, val); 00459 if (err) { 00460 PyErr_SetString(PyExc_KeyError, err ); 00461 return -1; 00462 } 00463 00464 return 0; 00465 } 00466 } 00467 00468 static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject *val) 00469 { 00470 return BPy_Wrap_SetMapItem(self->prop, key, val); 00471 } 00472 00473 static PyObject *BPy_IDGroup_iter(BPy_IDProperty *self) 00474 { 00475 BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type); 00476 iter->group = self; 00477 iter->mode = IDPROP_ITER_KEYS; 00478 iter->cur = self->prop->data.group.first; 00479 Py_XINCREF(iter); 00480 return (PyObject*) iter; 00481 } 00482 00483 static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) 00484 { 00485 switch (prop->type) { 00486 case IDP_STRING: 00487 #ifdef USE_STRING_COERCE 00488 return PyC_UnicodeFromByte(IDP_Array(prop)); 00489 #else 00490 return PyUnicode_FromString(IDP_Array(prop)); 00491 #endif 00492 break; 00493 case IDP_FLOAT: 00494 return PyFloat_FromDouble(*((float*)&prop->data.val)); 00495 break; 00496 case IDP_DOUBLE: 00497 return PyFloat_FromDouble(*((double*)&prop->data.val)); 00498 break; 00499 case IDP_INT: 00500 return PyLong_FromSsize_t( prop->data.val ); 00501 break; 00502 case IDP_ARRAY: 00503 { 00504 PyObject *seq = PyList_New(prop->len); 00505 int i; 00506 00507 if (!seq) { 00508 PyErr_Format(PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_ARRAY: PyList_New(%d) failed", prop->len); 00509 return NULL; 00510 } 00511 00512 switch(prop->subtype) { 00513 case IDP_FLOAT: 00514 { 00515 float *array= (float*)IDP_Array(prop); 00516 for (i=0; i<prop->len; i++) { 00517 PyList_SET_ITEM(seq, i, PyFloat_FromDouble(array[i])); 00518 } 00519 break; 00520 } 00521 case IDP_DOUBLE: 00522 { 00523 double *array= (double*)IDP_Array(prop); 00524 for (i=0; i<prop->len; i++) { 00525 PyList_SET_ITEM(seq, i, PyFloat_FromDouble(array[i])); 00526 } 00527 break; 00528 } 00529 case IDP_INT: 00530 { 00531 int *array= (int*)IDP_Array(prop); 00532 for (i=0; i<prop->len; i++) { 00533 PyList_SET_ITEM(seq, i, PyLong_FromLong(array[i])); 00534 } 00535 break; 00536 } 00537 default: 00538 PyErr_SetString(PyExc_RuntimeError, "invalid/corrupt array type!"); 00539 Py_DECREF(seq); 00540 return NULL; 00541 } 00542 00543 return seq; 00544 } 00545 case IDP_IDPARRAY: 00546 { 00547 PyObject *seq = PyList_New(prop->len), *wrap; 00548 IDProperty *array= IDP_IDPArray(prop); 00549 int i; 00550 00551 if (!seq) { 00552 PyErr_Format(PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len); 00553 return NULL; 00554 } 00555 00556 for (i=0; i<prop->len; i++) { 00557 wrap= BPy_IDGroup_MapDataToPy(array++); 00558 00559 if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */ 00560 return NULL; 00561 00562 PyList_SET_ITEM(seq, i, wrap); 00563 } 00564 return seq; 00565 } 00566 case IDP_GROUP: 00567 { 00568 PyObject *dict = PyDict_New(), *wrap; 00569 IDProperty *loop; 00570 00571 for (loop=prop->data.group.first; loop; loop=loop->next) { 00572 wrap = BPy_IDGroup_MapDataToPy(loop); 00573 00574 if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */ 00575 return NULL; 00576 00577 PyDict_SetItemString(dict, loop->name, wrap); 00578 Py_DECREF(wrap); 00579 } 00580 return dict; 00581 } 00582 } 00583 00584 PyErr_Format(PyExc_RuntimeError, "eek!! '%s' property exists with a bad type code '%d' !!!", prop->name, prop->type); 00585 return NULL; 00586 } 00587 00588 static PyObject *BPy_IDGroup_Pop(BPy_IDProperty *self, PyObject *value) 00589 { 00590 IDProperty *idprop; 00591 PyObject *pyform; 00592 char *name = _PyUnicode_AsString(value); 00593 00594 if (!name) { 00595 PyErr_SetString(PyExc_TypeError, "pop expected at least 1 argument, got 0"); 00596 return NULL; 00597 } 00598 00599 idprop= IDP_GetPropertyFromGroup(self->prop, name); 00600 00601 if(idprop) { 00602 pyform = BPy_IDGroup_MapDataToPy(idprop); 00603 00604 if (!pyform) { 00605 /*ok something bad happened with the pyobject, 00606 so don't remove the prop from the group. if pyform is 00607 NULL, then it already should have raised an exception.*/ 00608 return NULL; 00609 } 00610 00611 IDP_RemFromGroup(self->prop, idprop); 00612 return pyform; 00613 } 00614 00615 PyErr_SetString(PyExc_KeyError, "item not in group"); 00616 return NULL; 00617 } 00618 00619 static PyObject *BPy_IDGroup_IterItems(BPy_IDProperty *self) 00620 { 00621 BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type); 00622 iter->group = self; 00623 iter->mode = IDPROP_ITER_ITEMS; 00624 iter->cur = self->prop->data.group.first; 00625 Py_XINCREF(iter); 00626 return (PyObject*) iter; 00627 } 00628 00629 /* utility function */ 00630 static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len) 00631 { 00632 int j; 00633 00634 printf("ID Property Error found and corrected in BPy_IDGroup_GetKeys/Values/Items!\n"); 00635 00636 /*fill rest of list with valid references to None*/ 00637 for (j=len; j<prop->len; j++) { 00638 Py_INCREF(Py_None); 00639 PyList_SET_ITEM(seq, j, Py_None); 00640 } 00641 00642 /*set correct group length*/ 00643 prop->len = len; 00644 } 00645 00646 PyObject *BPy_Wrap_GetKeys(IDProperty *prop) 00647 { 00648 PyObject *seq = PyList_New(prop->len); 00649 IDProperty *loop; 00650 int i; 00651 00652 for (i=0, loop=prop->data.group.first; loop && (i < prop->len); loop=loop->next, i++) 00653 PyList_SET_ITEM(seq, i, PyUnicode_FromString(loop->name)); 00654 00655 /* if the id prop is corrupt, count the remaining */ 00656 for (; loop; loop=loop->next, i++) {} 00657 00658 if (i != prop->len) { /* if the loop didnt finish, we know the length is wrong */ 00659 BPy_IDGroup_CorrectListLen(prop, seq, i); 00660 Py_DECREF(seq); /*free the list*/ 00661 /*call self again*/ 00662 return BPy_Wrap_GetKeys(prop); 00663 } 00664 00665 return seq; 00666 } 00667 00668 PyObject *BPy_Wrap_GetValues(ID *id, IDProperty *prop) 00669 { 00670 PyObject *seq = PyList_New(prop->len); 00671 IDProperty *loop; 00672 int i; 00673 00674 for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) { 00675 PyList_SET_ITEM(seq, i, BPy_IDGroup_WrapData(id, loop)); 00676 } 00677 00678 if (i != prop->len) { 00679 BPy_IDGroup_CorrectListLen(prop, seq, i); 00680 Py_DECREF(seq); /*free the list*/ 00681 /*call self again*/ 00682 return BPy_Wrap_GetValues(id, prop); 00683 } 00684 00685 return seq; 00686 } 00687 00688 PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop) 00689 { 00690 PyObject *seq = PyList_New(prop->len); 00691 IDProperty *loop; 00692 int i; 00693 00694 for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) { 00695 PyObject *item= PyTuple_New(2); 00696 PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(loop->name)); 00697 PyTuple_SET_ITEM(item, 1, BPy_IDGroup_WrapData(id, loop)); 00698 PyList_SET_ITEM(seq, i, item); 00699 } 00700 00701 if (i != prop->len) { 00702 BPy_IDGroup_CorrectListLen(prop, seq, i); 00703 Py_DECREF(seq); /*free the list*/ 00704 /*call self again*/ 00705 return BPy_Wrap_GetItems(id, prop); 00706 } 00707 00708 return seq; 00709 } 00710 00711 00712 static PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self) 00713 { 00714 return BPy_Wrap_GetKeys(self->prop); 00715 } 00716 00717 static PyObject *BPy_IDGroup_GetValues(BPy_IDProperty *self) 00718 { 00719 return BPy_Wrap_GetValues(self->id, self->prop); 00720 } 00721 00722 static PyObject *BPy_IDGroup_GetItems(BPy_IDProperty *self) 00723 { 00724 return BPy_Wrap_GetItems(self->id, self->prop); 00725 } 00726 00727 static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value) 00728 { 00729 char *name = _PyUnicode_AsString(value); 00730 00731 if (!name) { 00732 PyErr_SetString(PyExc_TypeError, "expected a string"); 00733 return -1; 00734 } 00735 00736 return IDP_GetPropertyFromGroup(self->prop, name) ? 1:0; 00737 } 00738 00739 static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *value) 00740 { 00741 PyObject *pkey, *pval; 00742 Py_ssize_t i=0; 00743 00744 if (!PyDict_Check(value)) { 00745 PyErr_SetString(PyExc_TypeError, "expected an object derived from dict"); 00746 return NULL; 00747 } 00748 00749 while (PyDict_Next(value, &i, &pkey, &pval)) { 00750 BPy_IDGroup_Map_SetItem(self, pkey, pval); 00751 if (PyErr_Occurred()) return NULL; 00752 } 00753 00754 Py_RETURN_NONE; 00755 } 00756 00757 static PyObject *BPy_IDGroup_to_dict(BPy_IDProperty *self) 00758 { 00759 return BPy_IDGroup_MapDataToPy(self->prop); 00760 } 00761 00762 00763 /* Matches python dict.get(key, [default]) */ 00764 static PyObject* BPy_IDGroup_Get(BPy_IDProperty *self, PyObject *args) 00765 { 00766 IDProperty *idprop; 00767 char *key; 00768 PyObject* def = Py_None; 00769 00770 if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) 00771 return NULL; 00772 00773 idprop= IDP_GetPropertyFromGroup(self->prop, key); 00774 if (idprop) { 00775 PyObject* pyobj = BPy_IDGroup_WrapData(self->id, idprop); 00776 if (pyobj) 00777 return pyobj; 00778 } 00779 00780 Py_INCREF(def); 00781 return def; 00782 } 00783 00784 static struct PyMethodDef BPy_IDGroup_methods[] = { 00785 {"pop", (PyCFunction)BPy_IDGroup_Pop, METH_O, 00786 "pop an item from the group; raises KeyError if the item doesn't exist"}, 00787 {"iteritems", (PyCFunction)BPy_IDGroup_IterItems, METH_NOARGS, 00788 "iterate through the items in the dict; behaves like dictionary method iteritems"}, 00789 {"keys", (PyCFunction)BPy_IDGroup_GetKeys, METH_NOARGS, 00790 "get the keys associated with this group as a list of strings"}, 00791 {"values", (PyCFunction)BPy_IDGroup_GetValues, METH_NOARGS, 00792 "get the values associated with this group"}, 00793 {"items", (PyCFunction)BPy_IDGroup_GetItems, METH_NOARGS, 00794 "get the items associated with this group"}, 00795 {"update", (PyCFunction)BPy_IDGroup_Update, METH_O, 00796 "updates the values in the group with the values of another or a dict"}, 00797 {"get", (PyCFunction)BPy_IDGroup_Get, METH_VARARGS, 00798 "idprop.get(k[,d]) -> idprop[k] if k in idprop, else d. d defaults to None"}, 00799 {"to_dict", (PyCFunction)BPy_IDGroup_to_dict, METH_NOARGS, 00800 "return a purely python version of the group"}, 00801 {NULL, NULL, 0, NULL} 00802 }; 00803 00804 static PySequenceMethods BPy_IDGroup_Seq = { 00805 (lenfunc) BPy_IDGroup_Map_Len, /* lenfunc sq_length */ 00806 NULL, /* binaryfunc sq_concat */ 00807 NULL, /* ssizeargfunc sq_repeat */ 00808 NULL, /* ssizeargfunc sq_item */ /* TODO - setting this will allow PySequence_Check to return True */ 00809 NULL, /* intintargfunc ***was_sq_slice*** */ 00810 NULL, /* intobjargproc sq_ass_item */ 00811 NULL, /* ssizeobjargproc ***was_sq_ass_slice*** */ 00812 (objobjproc) BPy_IDGroup_Contains, /* objobjproc sq_contains */ 00813 NULL, /* binaryfunc sq_inplace_concat */ 00814 NULL, /* ssizeargfunc sq_inplace_repeat */ 00815 }; 00816 00817 static PyMappingMethods BPy_IDGroup_Mapping = { 00818 (lenfunc)BPy_IDGroup_Map_Len, /*inquiry mp_length */ 00819 (binaryfunc)BPy_IDGroup_Map_GetItem,/*binaryfunc mp_subscript */ 00820 (objobjargproc)BPy_IDGroup_Map_SetItem, /*objobjargproc mp_ass_subscript */ 00821 }; 00822 00823 PyTypeObject BPy_IDGroup_Type = { 00824 PyVarObject_HEAD_INIT(NULL, 0) 00825 /* For printing, in format "<module>.<name>" */ 00826 "Blender IDProperty", /* char *tp_name; */ 00827 sizeof(BPy_IDProperty), /* int tp_basicsize; */ 00828 0, /* tp_itemsize; For allocation */ 00829 00830 /* Methods to implement standard operations */ 00831 00832 NULL, /* destructor tp_dealloc; */ 00833 NULL, /* printfunc tp_print; */ 00834 NULL, /* getattrfunc tp_getattr; */ 00835 NULL, /* setattrfunc tp_setattr; */ 00836 NULL, /* cmpfunc tp_compare; */ 00837 (reprfunc)BPy_IDGroup_repr, /* reprfunc tp_repr; */ 00838 00839 /* Method suites for standard classes */ 00840 00841 NULL, /* PyNumberMethods *tp_as_number; */ 00842 &BPy_IDGroup_Seq, /* PySequenceMethods *tp_as_sequence; */ 00843 &BPy_IDGroup_Mapping, /* PyMappingMethods *tp_as_mapping; */ 00844 00845 /* More standard operations (here for binary compatibility) */ 00846 00847 (hashfunc)BPy_IDGroup_hash, /* hashfunc tp_hash; */ 00848 NULL, /* ternaryfunc tp_call; */ 00849 NULL, /* reprfunc tp_str; */ 00850 NULL, /* getattrofunc tp_getattro; */ 00851 NULL, /* setattrofunc tp_setattro; */ 00852 00853 /* Functions to access object as input/output buffer */ 00854 NULL, /* PyBufferProcs *tp_as_buffer; */ 00855 00856 /*** Flags to define presence of optional/expanded features ***/ 00857 Py_TPFLAGS_DEFAULT, /* long tp_flags; */ 00858 00859 NULL, /* char *tp_doc; Documentation string */ 00860 /*** Assigned meaning in release 2.0 ***/ 00861 /* call function for all accessible objects */ 00862 NULL, /* traverseproc tp_traverse; */ 00863 00864 /* delete references to contained objects */ 00865 NULL, /* inquiry tp_clear; */ 00866 00867 /*** Assigned meaning in release 2.1 ***/ 00868 /*** rich comparisons ***/ 00869 NULL, /* richcmpfunc tp_richcompare; */ 00870 00871 /*** weak reference enabler ***/ 00872 0, /* long tp_weaklistoffset; */ 00873 00874 /*** Added in release 2.2 ***/ 00875 /* Iterators */ 00876 (getiterfunc)BPy_IDGroup_iter, /* getiterfunc tp_iter; */ 00877 NULL, /* iternextfunc tp_iternext; */ 00878 /*** Attribute descriptor and subclassing stuff ***/ 00879 BPy_IDGroup_methods, /* struct PyMethodDef *tp_methods; */ 00880 NULL, /* struct PyMemberDef *tp_members; */ 00881 BPy_IDGroup_getseters, /* struct PyGetSetDef *tp_getset; */ 00882 }; 00883 00884 /*********** Main external wrapping function *******/ 00885 PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent) 00886 { 00887 BPy_IDProperty *wrap = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type); 00888 wrap->prop = prop; 00889 wrap->parent = parent; 00890 wrap->id = id; 00891 //wrap->destroy = 0; 00892 return (PyObject*) wrap; 00893 } 00894 00895 00896 /********Array Wrapper********/ 00897 00898 static PyTypeObject *idp_array_py_type(BPy_IDArray *self, short *is_double) 00899 { 00900 switch (self->prop->subtype) { 00901 case IDP_FLOAT: 00902 *is_double= 0; 00903 return &PyFloat_Type; 00904 case IDP_DOUBLE: 00905 *is_double= 1; 00906 return &PyFloat_Type; 00907 case IDP_INT: 00908 *is_double= 0; 00909 return &PyLong_Type; 00910 } 00911 00912 *is_double= 0; 00913 return NULL; 00914 } 00915 00916 static PyObject *BPy_IDArray_repr(BPy_IDArray *self) 00917 { 00918 return PyUnicode_FromFormat("<bpy id property array [%d]>", self->prop->len); 00919 } 00920 00921 static PyObject *BPy_IDArray_GetType(BPy_IDArray *self) 00922 { 00923 switch(self->prop->subtype) { 00924 case IDP_FLOAT: 00925 return PyUnicode_FromString("f"); 00926 case IDP_DOUBLE: 00927 return PyUnicode_FromString("d"); 00928 case IDP_INT: 00929 return PyUnicode_FromString("i"); 00930 } 00931 00932 PyErr_SetString(PyExc_RuntimeError, "invalid/corrupt array type!"); 00933 return NULL; 00934 } 00935 00936 static PyGetSetDef BPy_IDArray_getseters[] = { 00937 /* matches pythons array.typecode */ 00938 {(char *)"typecode", (getter)BPy_IDArray_GetType, (setter)NULL, (char *)"The type of the data in the array, is an int.", NULL}, 00939 {NULL, NULL, NULL, NULL, NULL}, 00940 }; 00941 00942 static PyObject *BPy_IDArray_to_list(BPy_IDArray *self) 00943 { 00944 return BPy_IDGroup_MapDataToPy(self->prop); 00945 } 00946 00947 static PyMethodDef BPy_IDArray_methods[] = { 00948 {"to_list", (PyCFunction)BPy_IDArray_to_list, METH_NOARGS, 00949 "return the array as a list"}, 00950 {NULL, NULL, 0, NULL} 00951 }; 00952 00953 static int BPy_IDArray_Len(BPy_IDArray *self) 00954 { 00955 return self->prop->len; 00956 } 00957 00958 static PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index) 00959 { 00960 if (index < 0 || index >= self->prop->len) { 00961 PyErr_SetString(PyExc_IndexError, "index out of range!"); 00962 return NULL; 00963 } 00964 00965 switch (self->prop->subtype) { 00966 case IDP_FLOAT: 00967 return PyFloat_FromDouble(((float*)IDP_Array(self->prop))[index]); 00968 case IDP_DOUBLE: 00969 return PyFloat_FromDouble(((double*)IDP_Array(self->prop))[index]); 00970 case IDP_INT: 00971 return PyLong_FromLong((long)((int*)IDP_Array(self->prop))[index]); 00972 } 00973 00974 PyErr_SetString(PyExc_RuntimeError, "invalid/corrupt array type!"); 00975 return NULL; 00976 } 00977 00978 static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value) 00979 { 00980 int i; 00981 float f; 00982 double d; 00983 00984 if (index < 0 || index >= self->prop->len) { 00985 PyErr_SetString(PyExc_RuntimeError, "index out of range!"); 00986 return -1; 00987 } 00988 00989 switch (self->prop->subtype) { 00990 case IDP_FLOAT: 00991 f= (float)PyFloat_AsDouble(value); 00992 if (f==-1 && PyErr_Occurred()) { 00993 PyErr_SetString(PyExc_TypeError, "expected a float"); 00994 return -1; 00995 } 00996 ((float*)IDP_Array(self->prop))[index] = f; 00997 break; 00998 case IDP_DOUBLE: 00999 d= PyFloat_AsDouble(value); 01000 if (d==-1 && PyErr_Occurred()) { 01001 PyErr_SetString(PyExc_TypeError, "expected a float"); 01002 return -1; 01003 } 01004 ((double*)IDP_Array(self->prop))[index] = d; 01005 break; 01006 case IDP_INT: 01007 i= PyLong_AsSsize_t(value); 01008 if (i==-1 && PyErr_Occurred()) { 01009 PyErr_SetString(PyExc_TypeError, "expected an int type"); 01010 return -1; 01011 } 01012 01013 ((int*)IDP_Array(self->prop))[index] = i; 01014 break; 01015 } 01016 return 0; 01017 } 01018 01019 static PySequenceMethods BPy_IDArray_Seq = { 01020 (lenfunc) BPy_IDArray_Len, /* inquiry sq_length */ 01021 NULL, /* binaryfunc sq_concat */ 01022 NULL, /* intargfunc sq_repeat */ 01023 (ssizeargfunc)BPy_IDArray_GetItem, /* intargfunc sq_item */ 01024 NULL, /* intintargfunc sq_slice */ 01025 (ssizeobjargproc)BPy_IDArray_SetItem,/* intobjargproc sq_ass_item */ 01026 NULL, /* intintobjargproc sq_ass_slice */ 01027 NULL, /* objobjproc sq_contains */ 01028 /* Added in release 2.0 */ 01029 NULL, /* binaryfunc sq_inplace_concat */ 01030 NULL, /* intargfunc sq_inplace_repeat */ 01031 }; 01032 01033 01034 01035 /* sequence slice (get): idparr[a:b] */ 01036 static PyObject *BPy_IDArray_slice(BPy_IDArray *self, int begin, int end) 01037 { 01038 IDProperty *prop= self->prop; 01039 PyObject *tuple; 01040 int count; 01041 01042 CLAMP(begin, 0, prop->len); 01043 if (end<0) end= prop->len+end+1; 01044 CLAMP(end, 0, prop->len); 01045 begin= MIN2(begin, end); 01046 01047 tuple= PyTuple_New(end - begin); 01048 01049 switch (prop->subtype) { 01050 case IDP_FLOAT: 01051 { 01052 float *array= (float*)IDP_Array(prop); 01053 for(count = begin; count < end; count++) { 01054 PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(array[count])); 01055 } 01056 break; 01057 } 01058 case IDP_DOUBLE: 01059 { 01060 double *array= (double*)IDP_Array(prop); 01061 for(count = begin; count < end; count++) { 01062 PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(array[count])); 01063 } 01064 break; 01065 } 01066 case IDP_INT: 01067 { 01068 int *array= (int*)IDP_Array(prop); 01069 for(count = begin; count < end; count++) { 01070 PyTuple_SET_ITEM(tuple, count - begin, PyLong_FromLong(array[count])); 01071 } 01072 break; 01073 } 01074 } 01075 01076 return tuple; 01077 } 01078 /* sequence slice (set): idparr[a:b] = value */ 01079 static int BPy_IDArray_ass_slice(BPy_IDArray *self, int begin, int end, PyObject *seq) 01080 { 01081 IDProperty *prop= self->prop; 01082 short is_double= 0; 01083 const PyTypeObject *py_type= idp_array_py_type(self, &is_double); 01084 const size_t elem_size= is_double ? sizeof(double) : sizeof(float); 01085 size_t alloc_len; 01086 size_t size; 01087 void *vec; 01088 01089 CLAMP(begin, 0, prop->len); 01090 CLAMP(end, 0, prop->len); 01091 begin = MIN2(begin, end); 01092 01093 size = (end - begin); 01094 alloc_len= size * elem_size; 01095 01096 vec= MEM_mallocN(alloc_len, "array assignment"); /* NOTE: we count on int/float being the same size here */ 01097 if(PyC_AsArray(vec, seq, size, py_type, is_double, "slice assignment: ") == -1) { 01098 MEM_freeN(vec); 01099 return -1; 01100 } 01101 01102 memcpy((void *)(((char *)IDP_Array(prop)) + (begin * elem_size)), vec, alloc_len); 01103 01104 MEM_freeN(vec); 01105 return 0; 01106 } 01107 01108 static PyObject *BPy_IDArray_subscript(BPy_IDArray* self, PyObject* item) 01109 { 01110 if (PyIndex_Check(item)) { 01111 Py_ssize_t i; 01112 i = PyNumber_AsSsize_t(item, PyExc_IndexError); 01113 if (i == -1 && PyErr_Occurred()) 01114 return NULL; 01115 if (i < 0) 01116 i += self->prop->len; 01117 return BPy_IDArray_GetItem(self, i); 01118 } 01119 else if (PySlice_Check(item)) { 01120 Py_ssize_t start, stop, step, slicelength; 01121 01122 if (PySlice_GetIndicesEx((void *)item, self->prop->len, &start, &stop, &step, &slicelength) < 0) 01123 return NULL; 01124 01125 if (slicelength <= 0) { 01126 return PyTuple_New(0); 01127 } 01128 else if (step == 1) { 01129 return BPy_IDArray_slice(self, start, stop); 01130 } 01131 else { 01132 PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); 01133 return NULL; 01134 } 01135 } 01136 else { 01137 PyErr_Format(PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name); 01138 return NULL; 01139 } 01140 } 01141 01142 static int BPy_IDArray_ass_subscript(BPy_IDArray* self, PyObject* item, PyObject* value) 01143 { 01144 if (PyIndex_Check(item)) { 01145 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); 01146 if (i == -1 && PyErr_Occurred()) 01147 return -1; 01148 if (i < 0) 01149 i += self->prop->len; 01150 return BPy_IDArray_SetItem(self, i, value); 01151 } 01152 else if (PySlice_Check(item)) { 01153 Py_ssize_t start, stop, step, slicelength; 01154 01155 if (PySlice_GetIndicesEx((void *)item, self->prop->len, &start, &stop, &step, &slicelength) < 0) 01156 return -1; 01157 01158 if (step == 1) 01159 return BPy_IDArray_ass_slice(self, start, stop, value); 01160 else { 01161 PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); 01162 return -1; 01163 } 01164 } 01165 else { 01166 PyErr_Format(PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name); 01167 return -1; 01168 } 01169 } 01170 01171 static PyMappingMethods BPy_IDArray_AsMapping = { 01172 (lenfunc)BPy_IDArray_Len, 01173 (binaryfunc)BPy_IDArray_subscript, 01174 (objobjargproc)BPy_IDArray_ass_subscript 01175 }; 01176 01177 01178 PyTypeObject BPy_IDArray_Type = { 01179 PyVarObject_HEAD_INIT(NULL, 0) 01180 /* For printing, in format "<module>.<name>" */ 01181 "Blender IDArray", /* char *tp_name; */ 01182 sizeof(BPy_IDArray), /* int tp_basicsize; */ 01183 0, /* tp_itemsize; For allocation */ 01184 01185 /* Methods to implement standard operations */ 01186 01187 NULL, /* destructor tp_dealloc; */ 01188 NULL, /* printfunc tp_print; */ 01189 NULL, /* getattrfunc tp_getattr; */ 01190 NULL, /* setattrfunc tp_setattr; */ 01191 NULL, /* cmpfunc tp_compare; */ 01192 (reprfunc)BPy_IDArray_repr, /* reprfunc tp_repr; */ 01193 01194 /* Method suites for standard classes */ 01195 01196 NULL, /* PyNumberMethods *tp_as_number; */ 01197 &BPy_IDArray_Seq, /* PySequenceMethods *tp_as_sequence; */ 01198 &BPy_IDArray_AsMapping, /* PyMappingMethods *tp_as_mapping; */ 01199 01200 /* More standard operations (here for binary compatibility) */ 01201 01202 NULL, /* hashfunc tp_hash; */ 01203 NULL, /* ternaryfunc tp_call; */ 01204 NULL, /* reprfunc tp_str; */ 01205 NULL, /* getattrofunc tp_getattro; */ 01206 NULL, /* setattrofunc tp_setattro; */ 01207 01208 /* Functions to access object as input/output buffer */ 01209 NULL, /* PyBufferProcs *tp_as_buffer; */ 01210 01211 /*** Flags to define presence of optional/expanded features ***/ 01212 Py_TPFLAGS_DEFAULT, /* long tp_flags; */ 01213 01214 NULL, /* char *tp_doc; Documentation string */ 01215 /*** Assigned meaning in release 2.0 ***/ 01216 /* call function for all accessible objects */ 01217 NULL, /* traverseproc tp_traverse; */ 01218 01219 /* delete references to contained objects */ 01220 NULL, /* inquiry tp_clear; */ 01221 01222 /*** Assigned meaning in release 2.1 ***/ 01223 /*** rich comparisons ***/ 01224 NULL, /* richcmpfunc tp_richcompare; */ 01225 01226 /*** weak reference enabler ***/ 01227 0, /* long tp_weaklistoffset; */ 01228 01229 /*** Added in release 2.2 ***/ 01230 /* Iterators */ 01231 NULL, /* getiterfunc tp_iter; */ 01232 NULL, /* iternextfunc tp_iternext; */ 01233 01234 /*** Attribute descriptor and subclassing stuff ***/ 01235 BPy_IDArray_methods, /* struct PyMethodDef *tp_methods; */ 01236 NULL, /* struct PyMemberDef *tp_members; */ 01237 BPy_IDArray_getseters, /* struct PyGetSetDef *tp_getset; */ 01238 NULL, /* struct _typeobject *tp_base; */ 01239 NULL, /* PyObject *tp_dict; */ 01240 NULL, /* descrgetfunc tp_descr_get; */ 01241 NULL, /* descrsetfunc tp_descr_set; */ 01242 0, /* long tp_dictoffset; */ 01243 NULL, /* initproc tp_init; */ 01244 NULL, /* allocfunc tp_alloc; */ 01245 NULL, /* newfunc tp_new; */ 01246 /* Low-level free-memory routine */ 01247 NULL, /* freefunc tp_free; */ 01248 /* For PyObject_IS_GC */ 01249 NULL, /* inquiry tp_is_gc; */ 01250 NULL, /* PyObject *tp_bases; */ 01251 /* method resolution order */ 01252 NULL, /* PyObject *tp_mro; */ 01253 NULL, /* PyObject *tp_cache; */ 01254 NULL, /* PyObject *tp_subclasses; */ 01255 NULL, /* PyObject *tp_weaklist; */ 01256 NULL 01257 }; 01258 01259 /*********** ID Property Group iterator ********/ 01260 01261 static PyObject *IDGroup_Iter_iterself(PyObject *self) 01262 { 01263 Py_XINCREF(self); 01264 return self; 01265 } 01266 01267 static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self) 01268 { 01269 return PyUnicode_FromFormat("(ID Property Group Iter \"%s\")", self->group->prop->name); 01270 } 01271 01272 static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self) 01273 { 01274 IDProperty *cur=NULL; 01275 PyObject *ret; 01276 01277 if (self->cur) { 01278 cur = self->cur; 01279 self->cur = self->cur->next; 01280 if (self->mode == IDPROP_ITER_ITEMS) { 01281 ret = PyTuple_New(2); 01282 PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(cur->name)); 01283 PyTuple_SET_ITEM(ret, 1, BPy_IDGroup_WrapData(self->group->id, cur)); 01284 return ret; 01285 } 01286 else { 01287 return PyUnicode_FromString(cur->name); 01288 } 01289 } 01290 else { 01291 PyErr_SetString(PyExc_StopIteration, "iterator at end"); 01292 return NULL; 01293 } 01294 } 01295 01296 PyTypeObject BPy_IDGroup_Iter_Type = { 01297 PyVarObject_HEAD_INIT(NULL, 0) 01298 /* For printing, in format "<module>.<name>" */ 01299 "Blender IDGroup_Iter", /* char *tp_name; */ 01300 sizeof( BPy_IDGroup_Iter ), /* int tp_basicsize; */ 01301 0, /* tp_itemsize; For allocation */ 01302 01303 /* Methods to implement standard operations */ 01304 01305 NULL, /* destructor tp_dealloc; */ 01306 NULL, /* printfunc tp_print; */ 01307 NULL, /* getattrfunc tp_getattr; */ 01308 NULL, /* setattrfunc tp_setattr; */ 01309 NULL, /* cmpfunc tp_compare; */ 01310 ( reprfunc ) IDGroup_Iter_repr, /* reprfunc tp_repr; */ 01311 01312 /* Method suites for standard classes */ 01313 01314 NULL, /* PyNumberMethods *tp_as_number; */ 01315 NULL, /* PySequenceMethods *tp_as_sequence; */ 01316 NULL, /* PyMappingMethods *tp_as_mapping; */ 01317 01318 /* More standard operations (here for binary compatibility) */ 01319 01320 NULL, /* hashfunc tp_hash; */ 01321 NULL, /* ternaryfunc tp_call; */ 01322 NULL, /* reprfunc tp_str; */ 01323 NULL, /* getattrofunc tp_getattro; */ 01324 NULL, /* setattrofunc tp_setattro; */ 01325 01326 /* Functions to access object as input/output buffer */ 01327 NULL, /* PyBufferProcs *tp_as_buffer; */ 01328 01329 /*** Flags to define presence of optional/expanded features ***/ 01330 Py_TPFLAGS_DEFAULT, /* long tp_flags; */ 01331 01332 NULL, /* char *tp_doc; Documentation string */ 01333 /*** Assigned meaning in release 2.0 ***/ 01334 /* call function for all accessible objects */ 01335 NULL, /* traverseproc tp_traverse; */ 01336 01337 /* delete references to contained objects */ 01338 NULL, /* inquiry tp_clear; */ 01339 01340 /*** Assigned meaning in release 2.1 ***/ 01341 /*** rich comparisons ***/ 01342 NULL, /* richcmpfunc tp_richcompare; */ 01343 01344 /*** weak reference enabler ***/ 01345 0, /* long tp_weaklistoffset; */ 01346 01347 /*** Added in release 2.2 ***/ 01348 /* Iterators */ 01349 IDGroup_Iter_iterself, /* getiterfunc tp_iter; */ 01350 (iternextfunc) BPy_Group_Iter_Next, /* iternextfunc tp_iternext; */ 01351 }; 01352 01353 void IDProp_Init_Types(void) 01354 { 01355 PyType_Ready(&BPy_IDGroup_Type); 01356 PyType_Ready(&BPy_IDGroup_Iter_Type); 01357 PyType_Ready(&BPy_IDArray_Type); 01358 }