Blender  V2.93
idprop_py_api.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <Python.h>
22 
23 #include "MEM_guardedalloc.h"
24 
25 #include "BLI_utildefines.h"
26 
27 #include "idprop_py_api.h"
28 
29 #include "BKE_idprop.h"
30 
31 #include "DNA_ID.h" /* ID property definitions. */
32 
33 #define USE_STRING_COERCE
34 
35 #ifdef USE_STRING_COERCE
36 # include "py_capi_utils.h"
37 #endif
38 
39 #include "python_utildefines.h"
40 
41 extern bool pyrna_id_FromPyObject(PyObject *obj, ID **id);
42 extern PyObject *pyrna_id_CreatePyObject(ID *id);
43 extern bool pyrna_id_CheckPyObject(PyObject *obj);
44 
45 /* -------------------------------------------------------------------- */
51 static PyObject *idprop_py_from_idp_string(const IDProperty *prop)
52 {
53  if (prop->subtype == IDP_STRING_SUB_BYTE) {
54  return PyBytes_FromStringAndSize(IDP_String(prop), prop->len);
55  }
56 
57 #ifdef USE_STRING_COERCE
58  return PyC_UnicodeFromByteAndSize(IDP_Array(prop), prop->len - 1);
59 #else
60  return PyUnicode_FromStringAndSize(IDP_String(prop), prop->len - 1);
61 #endif
62 }
63 
64 static PyObject *idprop_py_from_idp_int(const IDProperty *prop)
65 {
66  return PyLong_FromLong((long)IDP_Int(prop));
67 }
68 
69 static PyObject *idprop_py_from_idp_float(const IDProperty *prop)
70 {
71  return PyFloat_FromDouble((double)IDP_Float(prop));
72 }
73 
74 static PyObject *idprop_py_from_idp_double(const IDProperty *prop)
75 {
76  return PyFloat_FromDouble(IDP_Double(prop));
77 }
78 
79 static PyObject *idprop_py_from_idp_group(ID *id, IDProperty *prop, IDProperty *parent)
80 {
81  BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type);
82  group->id = id;
83  group->prop = prop;
84  group->parent = parent; /* can be NULL */
85  return (PyObject *)group;
86 }
87 
88 static PyObject *idprop_py_from_idp_id(IDProperty *prop)
89 {
90  return pyrna_id_CreatePyObject(prop->data.pointer);
91 }
92 
93 static PyObject *idprop_py_from_idp_array(ID *id, IDProperty *prop)
94 {
96  array->id = id;
97  array->prop = prop;
98  return (PyObject *)array;
99 }
100 
101 static PyObject *idprop_py_from_idp_idparray(ID *id, IDProperty *prop)
102 {
103  PyObject *seq = PyList_New(prop->len);
104  IDProperty *array = IDP_IDPArray(prop);
105  int i;
106 
107  if (!seq) {
108  PyErr_Format(
109  PyExc_RuntimeError, "%s: IDP_IDPARRAY: PyList_New(%d) failed", __func__, prop->len);
110  return NULL;
111  }
112 
113  for (i = 0; i < prop->len; i++) {
114  PyObject *wrap = BPy_IDGroup_WrapData(id, array++, prop);
115 
116  /* BPy_IDGroup_MapDataToPy sets the error */
117  if (UNLIKELY(wrap == NULL)) {
118  Py_DECREF(seq);
119  return NULL;
120  }
121 
122  PyList_SET_ITEM(seq, i, wrap);
123  }
124 
125  return seq;
126 }
127 
130 /* -------------------------------------------------------------------- */
134 /* use for both array and group */
135 static Py_hash_t BPy_IDGroup_hash(BPy_IDProperty *self)
136 {
137  return _Py_HashPointer(self->prop);
138 }
139 
140 static PyObject *BPy_IDGroup_repr(BPy_IDProperty *self)
141 {
142  return PyUnicode_FromFormat("<bpy id prop: owner=\"%s\", name=\"%s\", address=%p>",
143  self->id ? self->id->name : "<NONE>",
144  self->prop->name,
145  self->prop);
146 }
147 
148 PyObject *BPy_IDGroup_WrapData(ID *id, IDProperty *prop, IDProperty *parent)
149 {
150  switch (prop->type) {
151  case IDP_STRING:
152  return idprop_py_from_idp_string(prop);
153  case IDP_INT:
154  return idprop_py_from_idp_int(prop);
155  case IDP_FLOAT:
156  return idprop_py_from_idp_float(prop);
157  case IDP_DOUBLE:
158  return idprop_py_from_idp_double(prop);
159  case IDP_GROUP:
160  return idprop_py_from_idp_group(id, prop, parent);
161  case IDP_ARRAY:
162  return idprop_py_from_idp_array(id, prop);
163  case IDP_IDPARRAY:
164  return idprop_py_from_idp_idparray(id, prop); /* this could be better a internal type */
165  case IDP_ID:
166  return idprop_py_from_idp_id(prop);
167  default:
168  Py_RETURN_NONE;
169  }
170 }
171 
172 /* UNUSED, currently assignment overwrites into new properties, rather than setting in-place. */
173 #if 0
174 static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject *value)
175 {
176  switch (prop->type) {
177  case IDP_STRING: {
178  char *st;
179  if (!PyUnicode_Check(value)) {
180  PyErr_SetString(PyExc_TypeError, "expected a string!");
181  return -1;
182  }
183  /* NOTE: if this code is enabled, bytes support needs to be added */
184 # ifdef USE_STRING_COERCE
185  {
186  int alloc_len;
187  PyObject *value_coerce = NULL;
188 
189  st = (char *)PyC_UnicodeAsByte(value, &value_coerce);
190  alloc_len = strlen(st) + 1;
191 
192  st = PyUnicode_AsUTF8(value);
193  IDP_ResizeArray(prop, alloc_len);
194  memcpy(IDP_Array(prop), st, alloc_len);
195  Py_XDECREF(value_coerce);
196  }
197 # else
198  st = PyUnicode_AsUTF8(value);
199  IDP_ResizeArray(prop, strlen(st) + 1);
200  strcpy(IDP_Array(prop), st);
201 # endif
202 
203  return 0;
204  }
205 
206  case IDP_INT: {
207  int ivalue = PyLong_AsSsize_t(value);
208  if (ivalue == -1 && PyErr_Occurred()) {
209  PyErr_SetString(PyExc_TypeError, "expected an int type");
210  return -1;
211  }
212  IDP_Int(prop) = ivalue;
213  break;
214  }
215  case IDP_FLOAT: {
216  float fvalue = (float)PyFloat_AsDouble(value);
217  if (fvalue == -1 && PyErr_Occurred()) {
218  PyErr_SetString(PyExc_TypeError, "expected a float");
219  return -1;
220  }
221  IDP_Float(self->prop) = fvalue;
222  break;
223  }
224  case IDP_DOUBLE: {
225  double dvalue = PyFloat_AsDouble(value);
226  if (dvalue == -1 && PyErr_Occurred()) {
227  PyErr_SetString(PyExc_TypeError, "expected a float");
228  return -1;
229  }
230  IDP_Double(self->prop) = dvalue;
231  break;
232  }
233  default:
234  PyErr_SetString(PyExc_AttributeError, "attempt to set read-only attribute!");
235  return -1;
236  }
237  return 0;
238 }
239 #endif
240 
241 static PyObject *BPy_IDGroup_GetName(BPy_IDProperty *self, void *UNUSED(closure))
242 {
243  return PyUnicode_FromString(self->prop->name);
244 }
245 
246 static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUSED(closure))
247 {
248  const char *name;
249  Py_ssize_t name_size;
250 
251  if (!PyUnicode_Check(value)) {
252  PyErr_SetString(PyExc_TypeError, "expected a string!");
253  return -1;
254  }
255 
256  name = PyUnicode_AsUTF8AndSize(value, &name_size);
257 
258  if (name_size >= MAX_IDPROP_NAME) {
259  PyErr_SetString(PyExc_TypeError, "string length cannot exceed 63 characters!");
260  return -1;
261  }
262 
263  memcpy(self->prop->name, name, name_size);
264  return 0;
265 }
266 
267 #if 0
268 static PyObject *BPy_IDGroup_GetType(BPy_IDProperty *self)
269 {
270  return PyLong_FromLong(self->prop->type);
271 }
272 #endif
273 
274 static PyGetSetDef BPy_IDGroup_getseters[] = {
275  {"name",
276  (getter)BPy_IDGroup_GetName,
277  (setter)BPy_IDGroup_SetName,
278  "The name of this Group.",
279  NULL},
280  {NULL, NULL, NULL, NULL, NULL},
281 };
282 
283 static Py_ssize_t BPy_IDGroup_Map_Len(BPy_IDProperty *self)
284 {
285  if (self->prop->type != IDP_GROUP) {
286  PyErr_SetString(PyExc_TypeError, "len() of unsized object");
287  return -1;
288  }
289 
290  return self->prop->len;
291 }
292 
293 static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item)
294 {
295  IDProperty *idprop;
296  const char *name;
297 
298  if (self->prop->type != IDP_GROUP) {
299  PyErr_SetString(PyExc_TypeError, "unsubscriptable object");
300  return NULL;
301  }
302 
303  name = PyUnicode_AsUTF8(item);
304 
305  if (name == NULL) {
306  PyErr_SetString(PyExc_TypeError, "only strings are allowed as keys of ID properties");
307  return NULL;
308  }
309 
310  idprop = IDP_GetPropertyFromGroup(self->prop, name);
311 
312  if (idprop == NULL) {
313  PyErr_SetString(PyExc_KeyError, "key not in subgroup dict");
314  return NULL;
315  }
316 
317  return BPy_IDGroup_WrapData(self->id, idprop, self->prop);
318 }
319 
320 /* returns NULL on success, error string on failure */
321 static char idp_sequence_type(PyObject *seq_fast)
322 {
323  PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
324  PyObject *item;
325  char type = IDP_INT;
326 
327  Py_ssize_t i, len = PySequence_Fast_GET_SIZE(seq_fast);
328 
329  for (i = 0; i < len; i++) {
330  item = seq_fast_items[i];
331  if (PyFloat_Check(item)) {
332  if (type == IDP_IDPARRAY) { /* mixed dict/int */
333  return -1;
334  }
335  type = IDP_DOUBLE;
336  }
337  else if (PyLong_Check(item)) {
338  if (type == IDP_IDPARRAY) { /* mixed dict/int */
339  return -1;
340  }
341  }
342  else if (PyMapping_Check(item)) {
343  if (i != 0 && (type != IDP_IDPARRAY)) { /* mixed dict/int */
344  return -1;
345  }
346  type = IDP_IDPARRAY;
347  }
348  else {
349  return -1;
350  }
351  }
352 
353  return type;
354 }
355 
356 static const char *idp_try_read_name(PyObject *name_obj)
357 {
358  const char *name = NULL;
359  if (name_obj) {
360  Py_ssize_t name_size;
361  name = PyUnicode_AsUTF8AndSize(name_obj, &name_size);
362 
363  if (name == NULL) {
364  PyErr_Format(PyExc_KeyError,
365  "invalid id-property key, expected a string, not a %.200s",
366  Py_TYPE(name_obj)->tp_name);
367  return NULL;
368  }
369 
370  if (name_size >= MAX_IDPROP_NAME) {
371  PyErr_SetString(PyExc_KeyError,
372  "the length of IDProperty names is limited to 63 characters");
373  return NULL;
374  }
375  }
376  else {
377  name = "";
378  }
379  return name;
380 }
381 
384 /* -------------------------------------------------------------------- */
393 static IDProperty *idp_from_PyFloat(const char *name, PyObject *ob)
394 {
395  IDPropertyTemplate val = {0};
396  val.d = PyFloat_AsDouble(ob);
397  return IDP_New(IDP_DOUBLE, &val, name);
398 }
399 
400 static IDProperty *idp_from_PyLong(const char *name, PyObject *ob)
401 {
402  IDPropertyTemplate val = {0};
403  val.i = PyC_Long_AsI32(ob);
404  if (val.i == -1 && PyErr_Occurred()) {
405  return NULL;
406  }
407  return IDP_New(IDP_INT, &val, name);
408 }
409 
410 static IDProperty *idp_from_PyUnicode(const char *name, PyObject *ob)
411 {
412  IDProperty *prop;
413  IDPropertyTemplate val = {0};
414 #ifdef USE_STRING_COERCE
415  Py_ssize_t value_size;
416  PyObject *value_coerce = NULL;
417  val.string.str = PyC_UnicodeAsByteAndSize(ob, &value_size, &value_coerce);
418  val.string.len = (int)value_size + 1;
420  prop = IDP_New(IDP_STRING, &val, name);
421  Py_XDECREF(value_coerce);
422 #else
423  val.str = PyUnicode_AsUTF8(ob);
424  prop = IDP_New(IDP_STRING, val, name);
425 #endif
426  return prop;
427 }
428 
429 static IDProperty *idp_from_PyBytes(const char *name, PyObject *ob)
430 {
431  IDPropertyTemplate val = {0};
432  val.string.str = PyBytes_AS_STRING(ob);
433  val.string.len = PyBytes_GET_SIZE(ob);
435  return IDP_New(IDP_STRING, &val, name);
436 }
437 
438 static int idp_array_type_from_formatstr_and_size(const char *typestr, Py_ssize_t itemsize)
439 {
440  const char format = PyC_StructFmt_type_from_str(typestr);
441 
443  if (itemsize == 4) {
444  return IDP_FLOAT;
445  }
446  if (itemsize == 8) {
447  return IDP_DOUBLE;
448  }
449  }
451  if (itemsize == 4) {
452  return IDP_INT;
453  }
454  }
455 
456  return -1;
457 }
458 
459 static const char *idp_format_from_array_type(int type)
460 {
461  if (type == IDP_INT) {
462  return "i";
463  }
464  if (type == IDP_FLOAT) {
465  return "f";
466  }
467  if (type == IDP_DOUBLE) {
468  return "d";
469  }
470  return NULL;
471 }
472 
473 static IDProperty *idp_from_PySequence_Buffer(const char *name, Py_buffer *buffer)
474 {
475  IDProperty *prop;
476  IDPropertyTemplate val = {0};
477 
478  const int id_type = idp_array_type_from_formatstr_and_size(buffer->format, buffer->itemsize);
479  if (id_type == -1) {
480  /* should never happen as the type has been checked before */
481  return NULL;
482  }
483 
484  val.array.type = id_type;
485  val.array.len = buffer->len / buffer->itemsize;
486 
487  prop = IDP_New(IDP_ARRAY, &val, name);
488  memcpy(IDP_Array(prop), buffer->buf, buffer->len);
489  return prop;
490 }
491 
492 static IDProperty *idp_from_PySequence_Fast(const char *name, PyObject *ob)
493 {
494  IDProperty *prop;
495  IDPropertyTemplate val = {0};
496 
497  PyObject **ob_seq_fast_items;
498  PyObject *item;
499  int i;
500 
501  ob_seq_fast_items = PySequence_Fast_ITEMS(ob);
502 
503  if ((val.array.type = idp_sequence_type(ob)) == (char)-1) {
504  PyErr_SetString(PyExc_TypeError,
505  "only floats, ints and dicts are allowed in ID property arrays");
506  return NULL;
507  }
508 
509  /* validate sequence and derive type.
510  * we assume IDP_INT unless we hit a float
511  * number; then we assume it's */
512 
513  val.array.len = PySequence_Fast_GET_SIZE(ob);
514 
515  switch (val.array.type) {
516  case IDP_DOUBLE: {
517  double *prop_data;
518  prop = IDP_New(IDP_ARRAY, &val, name);
519  prop_data = IDP_Array(prop);
520  for (i = 0; i < val.array.len; i++) {
521  item = ob_seq_fast_items[i];
522  if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) {
523  IDP_FreeProperty(prop);
524  return NULL;
525  }
526  }
527  break;
528  }
529  case IDP_INT: {
530  int *prop_data;
531  prop = IDP_New(IDP_ARRAY, &val, name);
532  prop_data = IDP_Array(prop);
533  for (i = 0; i < val.array.len; i++) {
534  item = ob_seq_fast_items[i];
535  if (((prop_data[i] = PyC_Long_AsI32(item)) == -1) && PyErr_Occurred()) {
536  IDP_FreeProperty(prop);
537  return NULL;
538  }
539  }
540  break;
541  }
542  case IDP_IDPARRAY: {
543  prop = IDP_NewIDPArray(name);
544  for (i = 0; i < val.array.len; i++) {
545  item = ob_seq_fast_items[i];
546  if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) {
547  IDP_FreeProperty(prop);
548  return NULL;
549  }
550  }
551  break;
552  }
553  default:
554  /* should never happen */
555  PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type");
556  return NULL;
557  }
558  return prop;
559 }
560 
561 static IDProperty *idp_from_PySequence(const char *name, PyObject *ob)
562 {
563  Py_buffer buffer;
564  bool use_buffer = false;
565 
566  if (PyObject_CheckBuffer(ob)) {
567  PyObject_GetBuffer(ob, &buffer, PyBUF_SIMPLE | PyBUF_FORMAT);
568  const char format = PyC_StructFmt_type_from_str(buffer.format);
570  (PyC_StructFmt_type_is_int_any(format) && buffer.itemsize == 4)) {
571  use_buffer = true;
572  }
573  else {
574  PyBuffer_Release(&buffer);
575  }
576  }
577 
578  if (use_buffer) {
580  PyBuffer_Release(&buffer);
581  return prop;
582  }
583 
584  PyObject *ob_seq_fast = PySequence_Fast(ob, "py -> idprop");
585  if (ob_seq_fast != NULL) {
586  IDProperty *prop = idp_from_PySequence_Fast(name, ob_seq_fast);
587  Py_DECREF(ob_seq_fast);
588  return prop;
589  }
590 
591  return NULL;
592 }
593 
594 static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob)
595 {
596  IDProperty *prop;
597  const IDPropertyTemplate val = {0};
598 
599  PyObject *keys, *vals, *key, *pval;
600  int i, len;
601  /* yay! we get into recursive stuff now! */
602  keys = PyMapping_Keys(ob);
603  vals = PyMapping_Values(ob);
604 
605  /* we allocate the group first; if we hit any invalid data,
606  * we can delete it easily enough.*/
607  prop = IDP_New(IDP_GROUP, &val, name);
608  len = PyMapping_Length(ob);
609  for (i = 0; i < len; i++) {
610  key = PySequence_GetItem(keys, i);
611  pval = PySequence_GetItem(vals, i);
612  if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) {
613  IDP_FreeProperty(prop);
614  Py_XDECREF(keys);
615  Py_XDECREF(vals);
616  Py_XDECREF(key);
617  Py_XDECREF(pval);
618  /* error is already set */
619  return NULL;
620  }
621  Py_XDECREF(key);
622  Py_XDECREF(pval);
623  }
624  Py_XDECREF(keys);
625  Py_XDECREF(vals);
626  return prop;
627 }
628 
629 static IDProperty *idp_from_DatablockPointer(const char *name, PyObject *ob)
630 {
631  IDPropertyTemplate val = {0};
632  pyrna_id_FromPyObject(ob, &val.id);
633  return IDP_New(IDP_ID, &val, name);
634 }
635 
636 static IDProperty *idp_from_PyObject(PyObject *name_obj, PyObject *ob)
637 {
638  const char *name = idp_try_read_name(name_obj);
639  if (name == NULL) {
640  return NULL;
641  }
642 
643  if (PyFloat_Check(ob)) {
644  return idp_from_PyFloat(name, ob);
645  }
646  if (PyLong_Check(ob)) {
647  return idp_from_PyLong(name, ob);
648  }
649  if (PyUnicode_Check(ob)) {
650  return idp_from_PyUnicode(name, ob);
651  }
652  if (PyBytes_Check(ob)) {
653  return idp_from_PyBytes(name, ob);
654  }
655  if (PySequence_Check(ob)) {
656  return idp_from_PySequence(name, ob);
657  }
658  if (ob == Py_None || pyrna_id_CheckPyObject(ob)) {
659  return idp_from_DatablockPointer(name, ob);
660  }
661  if (PyMapping_Check(ob)) {
662  return idp_from_PyMapping(name, ob);
663  }
664 
665  PyErr_Format(
666  PyExc_TypeError, "invalid id-property type %.200s not supported", Py_TYPE(ob)->tp_name);
667  return NULL;
668 }
669 
672 /* -------------------------------------------------------------------- */
682 bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob)
683 {
684  IDProperty *prop = idp_from_PyObject(name_obj, ob);
685  if (prop == NULL) {
686  return false;
687  }
688 
689  if (group->type == IDP_IDPARRAY) {
690  IDP_AppendArray(group, prop);
691  /* IDP_AppendArray does a shallow copy (memcpy), only free memory */
692  MEM_freeN(prop);
693  }
694  else {
695  IDProperty *prop_exist;
696 
697  /* avoid freeing when types match in case they are referenced by the UI, see: T37073
698  * obviously this isn't a complete solution, but helps for common cases. */
699  prop_exist = IDP_GetPropertyFromGroup(group, prop->name);
700  if ((prop_exist != NULL) && (prop_exist->type == prop->type) &&
701  (prop_exist->subtype == prop->subtype)) {
702  /* Preserve prev/next links!!! See T42593. */
703  prop->prev = prop_exist->prev;
704  prop->next = prop_exist->next;
705  prop->flag = prop_exist->flag;
706 
707  IDP_FreePropertyContent(prop_exist);
708  *prop_exist = *prop;
709  MEM_freeN(prop);
710  }
711  else {
712  IDP_ReplaceInGroup_ex(group, prop, prop_exist);
713  }
714  }
715 
716  return true;
717 }
718 
719 int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val)
720 {
721  if (prop->type != IDP_GROUP) {
722  PyErr_SetString(PyExc_TypeError, "unsubscriptable object");
723  return -1;
724  }
725 
726  if (val == NULL) { /* del idprop[key] */
727  IDProperty *pkey;
728  const char *name = PyUnicode_AsUTF8(key);
729 
730  if (name == NULL) {
731  PyErr_Format(PyExc_KeyError, "expected a string, not %.200s", Py_TYPE(key)->tp_name);
732  return -1;
733  }
734 
735  pkey = IDP_GetPropertyFromGroup(prop, name);
736  if (pkey) {
737  IDP_FreeFromGroup(prop, pkey);
738  return 0;
739  }
740 
741  PyErr_SetString(PyExc_KeyError, "property not found in group");
742  return -1;
743  }
744 
745  bool ok;
746 
747  ok = BPy_IDProperty_Map_ValidateAndCreate(key, prop, val);
748  if (ok == false) {
749  return -1;
750  }
751 
752  return 0;
753 }
754 
755 static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject *val)
756 {
757  return BPy_Wrap_SetMapItem(self->prop, key, val);
758 }
759 
760 static PyObject *BPy_IDGroup_iter(BPy_IDProperty *self)
761 {
762  BPy_IDGroup_Iter *iter = PyObject_GC_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
763  iter->group = self;
764  Py_INCREF(self);
765  iter->mode = IDPROP_ITER_KEYS;
766  iter->cur = self->prop->data.group.first;
767  PyObject_GC_Track(iter);
768  return (PyObject *)iter;
769 }
770 
771 /* for simple, non nested types this is the same as BPy_IDGroup_WrapData */
773 {
774  switch (prop->type) {
775  case IDP_STRING:
776  return idprop_py_from_idp_string(prop);
777  case IDP_INT:
778  return idprop_py_from_idp_int(prop);
779  case IDP_FLOAT:
780  return idprop_py_from_idp_float(prop);
781  case IDP_DOUBLE:
782  return idprop_py_from_idp_double(prop);
783  case IDP_ID:
784  return idprop_py_from_idp_id(prop);
785  case IDP_ARRAY: {
786  PyObject *seq = PyList_New(prop->len);
787  int i;
788 
789  if (!seq) {
790  PyErr_Format(
791  PyExc_RuntimeError, "%s: IDP_ARRAY: PyList_New(%d) failed", __func__, prop->len);
792  return NULL;
793  }
794 
795  switch (prop->subtype) {
796  case IDP_FLOAT: {
797  const float *array = (float *)IDP_Array(prop);
798  for (i = 0; i < prop->len; i++) {
799  PyList_SET_ITEM(seq, i, PyFloat_FromDouble(array[i]));
800  }
801  break;
802  }
803  case IDP_DOUBLE: {
804  const double *array = (double *)IDP_Array(prop);
805  for (i = 0; i < prop->len; i++) {
806  PyList_SET_ITEM(seq, i, PyFloat_FromDouble(array[i]));
807  }
808  break;
809  }
810  case IDP_INT: {
811  const int *array = (int *)IDP_Array(prop);
812  for (i = 0; i < prop->len; i++) {
813  PyList_SET_ITEM(seq, i, PyLong_FromLong(array[i]));
814  }
815  break;
816  }
817  default:
818  PyErr_Format(
819  PyExc_RuntimeError, "%s: invalid/corrupt array type '%d'!", __func__, prop->subtype);
820  Py_DECREF(seq);
821  return NULL;
822  }
823 
824  return seq;
825  }
826  case IDP_IDPARRAY: {
827  PyObject *seq = PyList_New(prop->len);
828  IDProperty *array = IDP_IDPArray(prop);
829  int i;
830 
831  if (!seq) {
832  PyErr_Format(
833  PyExc_RuntimeError, "%s: IDP_IDPARRAY: PyList_New(%d) failed", __func__, prop->len);
834  return NULL;
835  }
836 
837  for (i = 0; i < prop->len; i++) {
838  PyObject *wrap = BPy_IDGroup_MapDataToPy(array++);
839 
840  /* BPy_IDGroup_MapDataToPy sets the error */
841  if (UNLIKELY(wrap == NULL)) {
842  Py_DECREF(seq);
843  return NULL;
844  }
845 
846  PyList_SET_ITEM(seq, i, wrap);
847  }
848  return seq;
849  }
850  case IDP_GROUP: {
851  PyObject *dict = _PyDict_NewPresized(prop->len);
852  IDProperty *loop;
853 
854  for (loop = prop->data.group.first; loop; loop = loop->next) {
855  PyObject *wrap = BPy_IDGroup_MapDataToPy(loop);
856 
857  /* BPy_IDGroup_MapDataToPy sets the error */
858  if (UNLIKELY(wrap == NULL)) {
859  Py_DECREF(dict);
860  return NULL;
861  }
862 
863  PyDict_SetItemString(dict, loop->name, wrap);
864  Py_DECREF(wrap);
865  }
866  return dict;
867  }
868  }
869 
870  PyErr_Format(PyExc_RuntimeError,
871  "%s ERROR: '%s' property exists with a bad type code '%d'!",
872  __func__,
873  prop->name,
874  prop->type);
875  return NULL;
876 }
877 
880 /* -------------------------------------------------------------------- */
885  BPy_IDGroup_pop_doc,
886  ".. method:: pop(key, default)\n"
887  "\n"
888  " Remove an item from the group, returning a Python representation.\n"
889  "\n"
890  " :raises KeyError: When the item doesn't exist.\n"
891  "\n"
892  " :arg key: Name of item to remove.\n"
893  " :type key: string\n"
894  " :arg default: Value to return when key isn't found, otherwise raise an exception.\n"
895  " :type default: Undefined\n");
896 static PyObject *BPy_IDGroup_pop(BPy_IDProperty *self, PyObject *args)
897 {
898  IDProperty *idprop;
899  PyObject *pyform;
900 
901  char *key;
902  PyObject *def = NULL;
903 
904  if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) {
905  return NULL;
906  }
907 
908  idprop = IDP_GetPropertyFromGroup(self->prop, key);
909  if (idprop == NULL) {
910  if (def == NULL) {
911  PyErr_SetString(PyExc_KeyError, "item not in group");
912  return NULL;
913  }
914  return Py_INCREF_RET(def);
915  }
916 
917  pyform = BPy_IDGroup_MapDataToPy(idprop);
918  if (pyform == NULL) {
919  /* ok something bad happened with the #PyObject,
920  * so don't remove the prop from the group. if pyform is
921  * NULL, then it already should have raised an exception.*/
922  return NULL;
923  }
924 
925  IDP_FreeFromGroup(self->prop, idprop);
926  return pyform;
927 }
928 
930  BPy_IDGroup_iter_items_doc,
931  ".. method:: iteritems()\n"
932  "\n"
933  " Iterate through the items in the dict; behaves like dictionary method iteritems.\n");
934 static PyObject *BPy_IDGroup_iter_items(BPy_IDProperty *self)
935 {
936  BPy_IDGroup_Iter *iter = PyObject_GC_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
937  iter->group = self;
938  Py_INCREF(self);
939  iter->mode = IDPROP_ITER_ITEMS;
940  iter->cur = self->prop->data.group.first;
941  PyObject_GC_Track(iter);
942  return (PyObject *)iter;
943 }
944 
945 /* utility function */
946 static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len, const char *func)
947 {
948  int j;
949 
950  printf("%s: ID Property Error found and corrected!\n", func);
951 
952  /* fill rest of list with valid references to None */
953  for (j = len; j < prop->len; j++) {
954  PyList_SET_ITEM(seq, j, Py_INCREF_RET(Py_None));
955  }
956 
957  /*set correct group length*/
958  prop->len = len;
959 }
960 
961 PyObject *BPy_Wrap_GetKeys(IDProperty *prop)
962 {
963  PyObject *list = PyList_New(prop->len);
964  IDProperty *loop;
965  int i;
966 
967  for (i = 0, loop = prop->data.group.first; loop && (i < prop->len); loop = loop->next, i++) {
968  PyList_SET_ITEM(list, i, PyUnicode_FromString(loop->name));
969  }
970 
971  /* if the id prop is corrupt, count the remaining */
972  for (; loop; loop = loop->next, i++) {
973  /* pass */
974  }
975 
976  if (i != prop->len) { /* if the loop didn't finish, we know the length is wrong */
977  BPy_IDGroup_CorrectListLen(prop, list, i, __func__);
978  Py_DECREF(list); /*free the list*/
979  /*call self again*/
980  return BPy_Wrap_GetKeys(prop);
981  }
982 
983  return list;
984 }
985 
986 PyObject *BPy_Wrap_GetValues(ID *id, IDProperty *prop)
987 {
988  PyObject *list = PyList_New(prop->len);
989  IDProperty *loop;
990  int i;
991 
992  for (i = 0, loop = prop->data.group.first; loop; loop = loop->next, i++) {
993  PyList_SET_ITEM(list, i, BPy_IDGroup_WrapData(id, loop, prop));
994  }
995 
996  if (i != prop->len) {
997  BPy_IDGroup_CorrectListLen(prop, list, i, __func__);
998  Py_DECREF(list); /*free the list*/
999  /*call self again*/
1000  return BPy_Wrap_GetValues(id, prop);
1001  }
1002 
1003  return list;
1004 }
1005 
1006 PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop)
1007 {
1008  PyObject *seq = PyList_New(prop->len);
1009  IDProperty *loop;
1010  int i;
1011 
1012  for (i = 0, loop = prop->data.group.first; loop; loop = loop->next, i++) {
1013  PyObject *item = PyTuple_New(2);
1015  item, PyUnicode_FromString(loop->name), BPy_IDGroup_WrapData(id, loop, prop));
1016  PyList_SET_ITEM(seq, i, item);
1017  }
1018 
1019  if (i != prop->len) {
1020  BPy_IDGroup_CorrectListLen(prop, seq, i, __func__);
1021  Py_DECREF(seq); /*free the list*/
1022  /*call self again*/
1023  return BPy_Wrap_GetItems(id, prop);
1024  }
1025 
1026  return seq;
1027 }
1028 
1029 PyDoc_STRVAR(BPy_IDGroup_keys_doc,
1030  ".. method:: keys()\n"
1031  "\n"
1032  " Return the keys associated with this group as a list of strings.\n");
1033 static PyObject *BPy_IDGroup_keys(BPy_IDProperty *self)
1034 {
1035  return BPy_Wrap_GetKeys(self->prop);
1036 }
1037 
1038 PyDoc_STRVAR(BPy_IDGroup_values_doc,
1039  ".. method:: values()\n"
1040  "\n"
1041  " Return the values associated with this group.\n");
1042 static PyObject *BPy_IDGroup_values(BPy_IDProperty *self)
1043 {
1044  return BPy_Wrap_GetValues(self->id, self->prop);
1045 }
1046 
1047 PyDoc_STRVAR(BPy_IDGroup_items_doc,
1048  ".. method:: items()\n"
1049  "\n"
1050  " Return the items associated with this group.\n");
1051 static PyObject *BPy_IDGroup_items(BPy_IDProperty *self)
1052 {
1053  return BPy_Wrap_GetItems(self->id, self->prop);
1054 }
1055 
1056 static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value)
1057 {
1058  const char *name = PyUnicode_AsUTF8(value);
1059 
1060  if (!name) {
1061  PyErr_Format(PyExc_TypeError, "expected a string, not a %.200s", Py_TYPE(value)->tp_name);
1062  return -1;
1063  }
1064 
1065  return IDP_GetPropertyFromGroup(self->prop, name) ? 1 : 0;
1066 }
1067 
1068 PyDoc_STRVAR(BPy_IDGroup_update_doc,
1069  ".. method:: update(other)\n"
1070  "\n"
1071  " Update key, values.\n"
1072  "\n"
1073  " :arg other: Updates the values in the group with this.\n"
1074  " :type other: :class:`IDPropertyGroup` or dict\n");
1075 static PyObject *BPy_IDGroup_update(BPy_IDProperty *self, PyObject *value)
1076 {
1077  PyObject *pkey, *pval;
1078  Py_ssize_t i = 0;
1079 
1080  if (BPy_IDGroup_Check(value)) {
1081  BPy_IDProperty *other = (BPy_IDProperty *)value;
1082  if (UNLIKELY(self->prop == other->prop)) {
1083  Py_RETURN_NONE;
1084  }
1085 
1086  /* XXX, possible one is inside the other */
1087  IDP_MergeGroup(self->prop, other->prop, true);
1088  }
1089  else if (PyDict_Check(value)) {
1090  while (PyDict_Next(value, &i, &pkey, &pval)) {
1091  BPy_IDGroup_Map_SetItem(self, pkey, pval);
1092  if (PyErr_Occurred()) {
1093  return NULL;
1094  }
1095  }
1096  }
1097  else {
1098  PyErr_Format(PyExc_TypeError,
1099  "expected a dict or an IDPropertyGroup type, not a %.200s",
1100  Py_TYPE(value)->tp_name);
1101  return NULL;
1102  }
1103 
1104  Py_RETURN_NONE;
1105 }
1106 
1107 PyDoc_STRVAR(BPy_IDGroup_to_dict_doc,
1108  ".. method:: to_dict()\n"
1109  "\n"
1110  " Return a purely python version of the group.\n");
1111 static PyObject *BPy_IDGroup_to_dict(BPy_IDProperty *self)
1112 {
1113  return BPy_IDGroup_MapDataToPy(self->prop);
1114 }
1115 
1116 PyDoc_STRVAR(BPy_IDGroup_clear_doc,
1117  ".. method:: clear()\n"
1118  "\n"
1119  " Clear all members from this group.\n");
1120 static PyObject *BPy_IDGroup_clear(BPy_IDProperty *self)
1121 {
1122  IDP_ClearProperty(self->prop);
1123  Py_RETURN_NONE;
1124 }
1125 
1126 PyDoc_STRVAR(BPy_IDGroup_get_doc,
1127  ".. method:: get(key, default=None)\n"
1128  "\n"
1129  " Return the value for key, if it exists, else default.\n");
1130 static PyObject *BPy_IDGroup_get(BPy_IDProperty *self, PyObject *args)
1131 {
1132  IDProperty *idprop;
1133  const char *key;
1134  PyObject *def = Py_None;
1135 
1136  if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) {
1137  return NULL;
1138  }
1139 
1140  idprop = IDP_GetPropertyFromGroup(self->prop, key);
1141  if (idprop) {
1142  PyObject *pyobj = BPy_IDGroup_WrapData(self->id, idprop, self->prop);
1143  if (pyobj) {
1144  return pyobj;
1145  }
1146  }
1147 
1148  Py_INCREF(def);
1149  return def;
1150 }
1151 
1152 static struct PyMethodDef BPy_IDGroup_methods[] = {
1153  {"pop", (PyCFunction)BPy_IDGroup_pop, METH_VARARGS, BPy_IDGroup_pop_doc},
1154  {"iteritems", (PyCFunction)BPy_IDGroup_iter_items, METH_NOARGS, BPy_IDGroup_iter_items_doc},
1155  {"keys", (PyCFunction)BPy_IDGroup_keys, METH_NOARGS, BPy_IDGroup_keys_doc},
1156  {"values", (PyCFunction)BPy_IDGroup_values, METH_NOARGS, BPy_IDGroup_values_doc},
1157  {"items", (PyCFunction)BPy_IDGroup_items, METH_NOARGS, BPy_IDGroup_items_doc},
1158  {"update", (PyCFunction)BPy_IDGroup_update, METH_O, BPy_IDGroup_update_doc},
1159  {"get", (PyCFunction)BPy_IDGroup_get, METH_VARARGS, BPy_IDGroup_get_doc},
1160  {"to_dict", (PyCFunction)BPy_IDGroup_to_dict, METH_NOARGS, BPy_IDGroup_to_dict_doc},
1161  {"clear", (PyCFunction)BPy_IDGroup_clear, METH_NOARGS, BPy_IDGroup_clear_doc},
1162  {NULL, NULL, 0, NULL},
1163 };
1164 
1167 /* -------------------------------------------------------------------- */
1171 static PySequenceMethods BPy_IDGroup_Seq = {
1172  (lenfunc)BPy_IDGroup_Map_Len, /* lenfunc sq_length */
1173  NULL, /* binaryfunc sq_concat */
1174  NULL, /* ssizeargfunc sq_repeat */
1175  NULL,
1176  /* ssizeargfunc sq_item */ /* TODO - setting this will allow PySequence_Check to return True */
1177  NULL, /* intintargfunc ***was_sq_slice*** */
1178  NULL, /* intobjargproc sq_ass_item */
1179  NULL, /* ssizeobjargproc ***was_sq_ass_slice*** */
1180  (objobjproc)BPy_IDGroup_Contains, /* objobjproc sq_contains */
1181  NULL, /* binaryfunc sq_inplace_concat */
1182  NULL, /* ssizeargfunc sq_inplace_repeat */
1183 };
1184 
1185 static PyMappingMethods BPy_IDGroup_Mapping = {
1186  (lenfunc)BPy_IDGroup_Map_Len, /*inquiry mp_length */
1187  (binaryfunc)BPy_IDGroup_Map_GetItem, /*binaryfunc mp_subscript */
1188  (objobjargproc)BPy_IDGroup_Map_SetItem, /*objobjargproc mp_ass_subscript */
1189 };
1190 
1191 PyTypeObject BPy_IDGroup_Type = {
1192  PyVarObject_HEAD_INIT(NULL, 0)
1193  /* For printing, in format "<module>.<name>" */
1194  "IDPropertyGroup", /* char *tp_name; */
1195  sizeof(BPy_IDProperty), /* int tp_basicsize; */
1196  0, /* tp_itemsize; For allocation */
1197 
1198  /* Methods to implement standard operations */
1199 
1200  NULL, /* destructor tp_dealloc; */
1201  0, /* tp_vectorcall_offset */
1202  NULL, /* getattrfunc tp_getattr; */
1203  NULL, /* setattrfunc tp_setattr; */
1204  NULL, /* cmpfunc tp_compare; */
1205  (reprfunc)BPy_IDGroup_repr, /* reprfunc tp_repr; */
1206 
1207  /* Method suites for standard classes */
1208 
1209  NULL, /* PyNumberMethods *tp_as_number; */
1210  &BPy_IDGroup_Seq, /* PySequenceMethods *tp_as_sequence; */
1211  &BPy_IDGroup_Mapping, /* PyMappingMethods *tp_as_mapping; */
1212 
1213  /* More standard operations (here for binary compatibility) */
1214 
1215  (hashfunc)BPy_IDGroup_hash, /* hashfunc tp_hash; */
1216  NULL, /* ternaryfunc tp_call; */
1217  NULL, /* reprfunc tp_str; */
1218  NULL, /* getattrofunc tp_getattro; */
1219  NULL, /* setattrofunc tp_setattro; */
1220 
1221  /* Functions to access object as input/output buffer */
1222  NULL, /* PyBufferProcs *tp_as_buffer; */
1223 
1224  /*** Flags to define presence of optional/expanded features ***/
1225  Py_TPFLAGS_DEFAULT, /* long tp_flags; */
1226 
1227  NULL, /* char *tp_doc; Documentation string */
1228  /*** Assigned meaning in release 2.0 ***/
1229  /* call function for all accessible objects */
1230  NULL, /* traverseproc tp_traverse; */
1231 
1232  /* delete references to contained objects */
1233  NULL, /* inquiry tp_clear; */
1234 
1235  /*** Assigned meaning in release 2.1 ***/
1236  /*** rich comparisons ***/
1237  NULL, /* richcmpfunc tp_richcompare; */
1238 
1239  /*** weak reference enabler ***/
1240  0, /* long tp_weaklistoffset; */
1241 
1242  /*** Added in release 2.2 ***/
1243  /* Iterators */
1244  (getiterfunc)BPy_IDGroup_iter, /* getiterfunc tp_iter; */
1245  NULL, /* iternextfunc tp_iternext; */
1246  /*** Attribute descriptor and subclassing stuff ***/
1247  BPy_IDGroup_methods, /* struct PyMethodDef *tp_methods; */
1248  NULL, /* struct PyMemberDef *tp_members; */
1249  BPy_IDGroup_getseters, /* struct PyGetSetDef *tp_getset; */
1250 };
1251 
1254 /* -------------------------------------------------------------------- */
1258 static PyTypeObject *idp_array_py_type(BPy_IDArray *self, bool *r_is_double)
1259 {
1260  switch (self->prop->subtype) {
1261  case IDP_FLOAT:
1262  *r_is_double = false;
1263  return &PyFloat_Type;
1264  case IDP_DOUBLE:
1265  *r_is_double = true;
1266  return &PyFloat_Type;
1267  case IDP_INT:
1268  *r_is_double = false;
1269  return &PyLong_Type;
1270  default:
1271  *r_is_double = false;
1272  return NULL;
1273  }
1274 }
1275 
1276 static PyObject *BPy_IDArray_repr(BPy_IDArray *self)
1277 {
1278  return PyUnicode_FromFormat("<bpy id property array [%d]>", self->prop->len);
1279 }
1280 
1281 PyDoc_STRVAR(BPy_IDArray_get_typecode_doc,
1282  "The type of the data in the array {'f': float, 'd': double, 'i': int}.");
1283 static PyObject *BPy_IDArray_get_typecode(BPy_IDArray *self)
1284 {
1285  switch (self->prop->subtype) {
1286  case IDP_FLOAT:
1287  return PyUnicode_FromString("f");
1288  case IDP_DOUBLE:
1289  return PyUnicode_FromString("d");
1290  case IDP_INT:
1291  return PyUnicode_FromString("i");
1292  }
1293 
1294  PyErr_Format(
1295  PyExc_RuntimeError, "%s: invalid/corrupt array type '%d'!", __func__, self->prop->subtype);
1296 
1297  return NULL;
1298 }
1299 
1300 static PyGetSetDef BPy_IDArray_getseters[] = {
1301  /* matches pythons array.typecode */
1302  {"typecode",
1303  (getter)BPy_IDArray_get_typecode,
1304  (setter)NULL,
1305  BPy_IDArray_get_typecode_doc,
1306  NULL},
1307  {NULL, NULL, NULL, NULL, NULL},
1308 };
1309 
1310 PyDoc_STRVAR(BPy_IDArray_to_list_doc,
1311  ".. method:: to_list()\n"
1312  "\n"
1313  " Return the array as a list.\n");
1314 static PyObject *BPy_IDArray_to_list(BPy_IDArray *self)
1315 {
1316  return BPy_IDGroup_MapDataToPy(self->prop);
1317 }
1318 
1319 static PyMethodDef BPy_IDArray_methods[] = {
1320  {"to_list", (PyCFunction)BPy_IDArray_to_list, METH_NOARGS, BPy_IDArray_to_list_doc},
1321  {NULL, NULL, 0, NULL},
1322 };
1323 
1324 static int BPy_IDArray_Len(BPy_IDArray *self)
1325 {
1326  return self->prop->len;
1327 }
1328 
1329 static PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index)
1330 {
1331  if (index < 0 || index >= self->prop->len) {
1332  PyErr_SetString(PyExc_IndexError, "index out of range!");
1333  return NULL;
1334  }
1335 
1336  switch (self->prop->subtype) {
1337  case IDP_FLOAT:
1338  return PyFloat_FromDouble(((float *)IDP_Array(self->prop))[index]);
1339  case IDP_DOUBLE:
1340  return PyFloat_FromDouble(((double *)IDP_Array(self->prop))[index]);
1341  case IDP_INT:
1342  return PyLong_FromLong((long)((int *)IDP_Array(self->prop))[index]);
1343  }
1344 
1345  PyErr_Format(
1346  PyExc_RuntimeError, "%s: invalid/corrupt array type '%d'!", __func__, self->prop->subtype);
1347 
1348  return NULL;
1349 }
1350 
1351 static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
1352 {
1353  if (index < 0 || index >= self->prop->len) {
1354  PyErr_SetString(PyExc_RuntimeError, "index out of range!");
1355  return -1;
1356  }
1357 
1358  switch (self->prop->subtype) {
1359  case IDP_FLOAT: {
1360  const float f = (float)PyFloat_AsDouble(value);
1361  if (f == -1 && PyErr_Occurred()) {
1362  return -1;
1363  }
1364  ((float *)IDP_Array(self->prop))[index] = f;
1365  break;
1366  }
1367  case IDP_DOUBLE: {
1368  const double d = PyFloat_AsDouble(value);
1369  if (d == -1 && PyErr_Occurred()) {
1370  return -1;
1371  }
1372  ((double *)IDP_Array(self->prop))[index] = d;
1373  break;
1374  }
1375  case IDP_INT: {
1376  const int i = PyC_Long_AsI32(value);
1377  if (i == -1 && PyErr_Occurred()) {
1378  return -1;
1379  }
1380 
1381  ((int *)IDP_Array(self->prop))[index] = i;
1382  break;
1383  }
1384  }
1385  return 0;
1386 }
1387 
1388 static PySequenceMethods BPy_IDArray_Seq = {
1389  (lenfunc)BPy_IDArray_Len, /* inquiry sq_length */
1390  NULL, /* binaryfunc sq_concat */
1391  NULL, /* intargfunc sq_repeat */
1392  (ssizeargfunc)BPy_IDArray_GetItem, /* intargfunc sq_item */
1393  NULL, /* intintargfunc sq_slice */
1394  (ssizeobjargproc)BPy_IDArray_SetItem, /* intobjargproc sq_ass_item */
1395  NULL, /* intintobjargproc sq_ass_slice */
1396  NULL, /* objobjproc sq_contains */
1397  /* Added in release 2.0 */
1398  NULL, /* binaryfunc sq_inplace_concat */
1399  NULL, /* intargfunc sq_inplace_repeat */
1400 };
1401 
1402 /* sequence slice (get): idparr[a:b] */
1403 static PyObject *BPy_IDArray_slice(BPy_IDArray *self, int begin, int end)
1404 {
1405  IDProperty *prop = self->prop;
1406  PyObject *tuple;
1407  int count;
1408 
1409  CLAMP(begin, 0, prop->len);
1410  if (end < 0) {
1411  end = prop->len + end + 1;
1412  }
1413  CLAMP(end, 0, prop->len);
1414  begin = MIN2(begin, end);
1415 
1416  tuple = PyTuple_New(end - begin);
1417 
1418  switch (prop->subtype) {
1419  case IDP_FLOAT: {
1420  const float *array = (float *)IDP_Array(prop);
1421  for (count = begin; count < end; count++) {
1422  PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(array[count]));
1423  }
1424  break;
1425  }
1426  case IDP_DOUBLE: {
1427  const double *array = (double *)IDP_Array(prop);
1428  for (count = begin; count < end; count++) {
1429  PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(array[count]));
1430  }
1431  break;
1432  }
1433  case IDP_INT: {
1434  const int *array = (int *)IDP_Array(prop);
1435  for (count = begin; count < end; count++) {
1436  PyTuple_SET_ITEM(tuple, count - begin, PyLong_FromLong(array[count]));
1437  }
1438  break;
1439  }
1440  }
1441 
1442  return tuple;
1443 }
1444 /* sequence slice (set): idparr[a:b] = value */
1445 static int BPy_IDArray_ass_slice(BPy_IDArray *self, int begin, int end, PyObject *seq)
1446 {
1447  IDProperty *prop = self->prop;
1448  bool is_double;
1449  const PyTypeObject *py_type = idp_array_py_type(self, &is_double);
1450  const size_t elem_size = is_double ? sizeof(double) : sizeof(float);
1451  size_t alloc_len;
1452  size_t size;
1453  void *vec;
1454 
1455  CLAMP(begin, 0, prop->len);
1456  CLAMP(end, 0, prop->len);
1457  begin = MIN2(begin, end);
1458 
1459  size = (end - begin);
1460  alloc_len = size * elem_size;
1461 
1462  /* NOTE: we count on int/float being the same size here */
1463  vec = MEM_mallocN(alloc_len, "array assignment");
1464 
1465  if (PyC_AsArray(vec, seq, size, py_type, is_double, "slice assignment: ") == -1) {
1466  MEM_freeN(vec);
1467  return -1;
1468  }
1469 
1470  memcpy((void *)(((char *)IDP_Array(prop)) + (begin * elem_size)), vec, alloc_len);
1471 
1472  MEM_freeN(vec);
1473  return 0;
1474 }
1475 
1476 static PyObject *BPy_IDArray_subscript(BPy_IDArray *self, PyObject *item)
1477 {
1478  if (PyIndex_Check(item)) {
1479  Py_ssize_t i;
1480  i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1481  if (i == -1 && PyErr_Occurred()) {
1482  return NULL;
1483  }
1484  if (i < 0) {
1485  i += self->prop->len;
1486  }
1487  return BPy_IDArray_GetItem(self, i);
1488  }
1489  if (PySlice_Check(item)) {
1490  Py_ssize_t start, stop, step, slicelength;
1491 
1492  if (PySlice_GetIndicesEx(item, self->prop->len, &start, &stop, &step, &slicelength) < 0) {
1493  return NULL;
1494  }
1495 
1496  if (slicelength <= 0) {
1497  return PyTuple_New(0);
1498  }
1499  if (step == 1) {
1500  return BPy_IDArray_slice(self, start, stop);
1501  }
1502 
1503  PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors");
1504  return NULL;
1505  }
1506 
1507  PyErr_Format(PyExc_TypeError,
1508  "vector indices must be integers, not %.200s",
1509  __func__,
1510  Py_TYPE(item)->tp_name);
1511  return NULL;
1512 }
1513 
1514 static int BPy_IDArray_ass_subscript(BPy_IDArray *self, PyObject *item, PyObject *value)
1515 {
1516  if (PyIndex_Check(item)) {
1517  Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1518  if (i == -1 && PyErr_Occurred()) {
1519  return -1;
1520  }
1521  if (i < 0) {
1522  i += self->prop->len;
1523  }
1524  return BPy_IDArray_SetItem(self, i, value);
1525  }
1526  if (PySlice_Check(item)) {
1527  Py_ssize_t start, stop, step, slicelength;
1528 
1529  if (PySlice_GetIndicesEx(item, self->prop->len, &start, &stop, &step, &slicelength) < 0) {
1530  return -1;
1531  }
1532 
1533  if (step == 1) {
1534  return BPy_IDArray_ass_slice(self, start, stop, value);
1535  }
1536 
1537  PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors");
1538  return -1;
1539  }
1540 
1541  PyErr_Format(
1542  PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
1543  return -1;
1544 }
1545 
1546 static PyMappingMethods BPy_IDArray_AsMapping = {
1547  (lenfunc)BPy_IDArray_Len,
1548  (binaryfunc)BPy_IDArray_subscript,
1549  (objobjargproc)BPy_IDArray_ass_subscript,
1550 };
1551 
1552 static int itemsize_by_idarray_type(int array_type)
1553 {
1554  if (array_type == IDP_INT) {
1555  return sizeof(int);
1556  }
1557  if (array_type == IDP_FLOAT) {
1558  return sizeof(float);
1559  }
1560  if (array_type == IDP_DOUBLE) {
1561  return sizeof(double);
1562  }
1563  return -1; /* should never happen */
1564 }
1565 
1566 static int BPy_IDArray_getbuffer(BPy_IDArray *self, Py_buffer *view, int flags)
1567 {
1568  IDProperty *prop = self->prop;
1569  const int itemsize = itemsize_by_idarray_type(prop->subtype);
1570  const int length = itemsize * prop->len;
1571 
1572  if (PyBuffer_FillInfo(view, (PyObject *)self, IDP_Array(prop), length, false, flags) == -1) {
1573  return -1;
1574  }
1575 
1576  view->itemsize = itemsize;
1577  view->format = (char *)idp_format_from_array_type(prop->subtype);
1578 
1579  Py_ssize_t *shape = MEM_mallocN(sizeof(Py_ssize_t), __func__);
1580  shape[0] = prop->len;
1581  view->shape = shape;
1582 
1583  return 0;
1584 }
1585 
1586 static void BPy_IDArray_releasebuffer(BPy_IDArray *UNUSED(self), Py_buffer *view)
1587 {
1588  MEM_freeN(view->shape);
1589 }
1590 
1591 static PyBufferProcs BPy_IDArray_Buffer = {
1592  (getbufferproc)BPy_IDArray_getbuffer,
1593  (releasebufferproc)BPy_IDArray_releasebuffer,
1594 };
1595 
1596 /* -------------------------------------------------------------------- */
1600 PyTypeObject BPy_IDArray_Type = {
1601  PyVarObject_HEAD_INIT(NULL, 0)
1602  /* For printing, in format "<module>.<name>" */
1603  "IDPropertyArray", /* char *tp_name; */
1604  sizeof(BPy_IDArray), /* int tp_basicsize; */
1605  0, /* tp_itemsize; For allocation */
1606 
1607  /* Methods to implement standard operations */
1608 
1609  NULL, /* destructor tp_dealloc; */
1610  0, /* tp_vectorcall_offset */
1611  NULL, /* getattrfunc tp_getattr; */
1612  NULL, /* setattrfunc tp_setattr; */
1613  NULL, /* cmpfunc tp_compare; */
1614  (reprfunc)BPy_IDArray_repr, /* reprfunc tp_repr; */
1615 
1616  /* Method suites for standard classes */
1617 
1618  NULL, /* PyNumberMethods *tp_as_number; */
1619  &BPy_IDArray_Seq, /* PySequenceMethods *tp_as_sequence; */
1620  &BPy_IDArray_AsMapping, /* PyMappingMethods *tp_as_mapping; */
1621 
1622  /* More standard operations (here for binary compatibility) */
1623 
1624  NULL, /* hashfunc tp_hash; */
1625  NULL, /* ternaryfunc tp_call; */
1626  NULL, /* reprfunc tp_str; */
1627  NULL, /* getattrofunc tp_getattro; */
1628  NULL, /* setattrofunc tp_setattro; */
1629 
1630  /* Functions to access object as input/output buffer */
1631  &BPy_IDArray_Buffer, /* PyBufferProcs *tp_as_buffer; */
1632 
1633  /*** Flags to define presence of optional/expanded features ***/
1634  Py_TPFLAGS_DEFAULT, /* long tp_flags; */
1635 
1636  NULL, /* char *tp_doc; Documentation string */
1637  /*** Assigned meaning in release 2.0 ***/
1638  /* call function for all accessible objects */
1639  NULL, /* traverseproc tp_traverse; */
1640 
1641  /* delete references to contained objects */
1642  NULL, /* inquiry tp_clear; */
1643 
1644  /*** Assigned meaning in release 2.1 ***/
1645  /*** rich comparisons ***/
1646  NULL, /* richcmpfunc tp_richcompare; */
1647 
1648  /*** weak reference enabler ***/
1649  0, /* long tp_weaklistoffset; */
1650 
1651  /*** Added in release 2.2 ***/
1652  /* Iterators */
1653  NULL, /* getiterfunc tp_iter; */
1654  NULL, /* iternextfunc tp_iternext; */
1655 
1656  /*** Attribute descriptor and subclassing stuff ***/
1657  BPy_IDArray_methods, /* struct PyMethodDef *tp_methods; */
1658  NULL, /* struct PyMemberDef *tp_members; */
1659  BPy_IDArray_getseters, /* struct PyGetSetDef *tp_getset; */
1660  NULL, /* struct _typeobject *tp_base; */
1661  NULL, /* PyObject *tp_dict; */
1662  NULL, /* descrgetfunc tp_descr_get; */
1663  NULL, /* descrsetfunc tp_descr_set; */
1664  0, /* long tp_dictoffset; */
1665  NULL, /* initproc tp_init; */
1666  NULL, /* allocfunc tp_alloc; */
1667  NULL, /* newfunc tp_new; */
1668  /* Low-level free-memory routine */
1669  NULL, /* freefunc tp_free; */
1670  /* For PyObject_IS_GC */
1671  NULL, /* inquiry tp_is_gc; */
1672  NULL, /* PyObject *tp_bases; */
1673  /* method resolution order */
1674  NULL, /* PyObject *tp_mro; */
1675  NULL, /* PyObject *tp_cache; */
1676  NULL, /* PyObject *tp_subclasses; */
1677  NULL, /* PyObject *tp_weaklist; */
1678  NULL,
1679 };
1680 
1683 /* -------------------------------------------------------------------- */
1687 static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
1688 {
1689  return PyUnicode_FromFormat("(ID Property Group Iter \"%s\")", self->group->prop->name);
1690 }
1691 
1693 {
1694  PyObject_GC_UnTrack(self);
1695  Py_CLEAR(self->group);
1696  PyObject_GC_Del(self);
1697 }
1698 
1699 static int BPy_IDGroup_Iter_traverse(BPy_IDGroup_Iter *self, visitproc visit, void *arg)
1700 {
1701  Py_VISIT(self->group);
1702  return 0;
1703 }
1704 
1706 {
1707  Py_CLEAR(self->group);
1708  return 0;
1709 }
1710 
1711 static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
1712 {
1713 
1714  if (self->cur) {
1715  PyObject *ret;
1716  IDProperty *cur;
1717 
1718  cur = self->cur;
1719  self->cur = self->cur->next;
1720 
1721  if (self->mode == IDPROP_ITER_ITEMS) {
1722  ret = PyTuple_New(2);
1724  PyUnicode_FromString(cur->name),
1725  BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop));
1726  return ret;
1727  }
1728 
1729  return PyUnicode_FromString(cur->name);
1730  }
1731 
1732  PyErr_SetNone(PyExc_StopIteration);
1733  return NULL;
1734 }
1735 
1736 PyTypeObject BPy_IDGroup_Iter_Type = {
1737  PyVarObject_HEAD_INIT(NULL, 0)
1738  /* For printing, in format "<module>.<name>" */
1739  "IDPropertyGroupIter", /* char *tp_name; */
1740  sizeof(BPy_IDGroup_Iter), /* int tp_basicsize; */
1741  0, /* tp_itemsize; For allocation */
1742 
1743  /* Methods to implement standard operations */
1744 
1745  (destructor)BPy_IDGroup_Iter_dealloc, /* tp_dealloc */
1746  0, /* tp_vectorcall_offset */
1747  NULL, /* getattrfunc tp_getattr; */
1748  NULL, /* setattrfunc tp_setattr; */
1749  NULL, /* cmpfunc tp_compare; */
1750  (reprfunc)IDGroup_Iter_repr, /* reprfunc tp_repr; */
1751 
1752  /* Method suites for standard classes */
1753 
1754  NULL, /* PyNumberMethods *tp_as_number; */
1755  NULL, /* PySequenceMethods *tp_as_sequence; */
1756  NULL, /* PyMappingMethods *tp_as_mapping; */
1757 
1758  /* More standard operations (here for binary compatibility) */
1759 
1760  NULL, /* hashfunc tp_hash; */
1761  NULL, /* ternaryfunc tp_call; */
1762  NULL, /* reprfunc tp_str; */
1763  NULL, /* getattrofunc tp_getattro; */
1764  NULL, /* setattrofunc tp_setattro; */
1765 
1766  /* Functions to access object as input/output buffer */
1767  NULL, /* PyBufferProcs *tp_as_buffer; */
1768 
1769  /*** Flags to define presence of optional/expanded features ***/
1770  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */
1771 
1772  NULL, /* char *tp_doc; Documentation string */
1773  /*** Assigned meaning in release 2.0 ***/
1774  /* call function for all accessible objects */
1775  (traverseproc)BPy_IDGroup_Iter_traverse, /* traverseproc tp_traverse; */
1776 
1777  /* delete references to contained objects */
1778  (inquiry)BPy_IDGroup_Iter_clear, /* inquiry tp_clear; */
1779 
1780  /*** Assigned meaning in release 2.1 ***/
1781  /*** rich comparisons ***/
1782  NULL, /* richcmpfunc tp_richcompare; */
1783 
1784  /*** weak reference enabler ***/
1785  0, /* long tp_weaklistoffset; */
1786 
1787  /*** Added in release 2.2 ***/
1788  /* Iterators */
1789  PyObject_SelfIter, /* getiterfunc tp_iter; */
1790  (iternextfunc)BPy_Group_Iter_Next, /* iternextfunc tp_iternext; */
1791 };
1792 
1794 {
1795  PyType_Ready(&BPy_IDGroup_Type);
1796  PyType_Ready(&BPy_IDGroup_Iter_Type);
1797  PyType_Ready(&BPy_IDArray_Type);
1798 }
1799 
1802 /* -------------------------------------------------------------------- */
1806 static struct PyModuleDef IDProp_types_module_def = {
1807  PyModuleDef_HEAD_INIT,
1808  "idprop.types", /* m_name */
1809  NULL, /* m_doc */
1810  0, /* m_size */
1811  NULL, /* m_methods */
1812  NULL, /* m_reload */
1813  NULL, /* m_traverse */
1814  NULL, /* m_clear */
1815  NULL, /* m_free */
1816 };
1817 
1818 static PyObject *BPyInit_idprop_types(void)
1819 {
1820  PyObject *submodule;
1821 
1822  submodule = PyModule_Create(&IDProp_types_module_def);
1823 
1825 
1826  /* bmesh_py_types.c */
1827  PyModule_AddType(submodule, &BPy_IDGroup_Type);
1828  PyModule_AddType(submodule, &BPy_IDGroup_Iter_Type);
1829  PyModule_AddType(submodule, &BPy_IDArray_Type);
1830 
1831  return submodule;
1832 }
1833 
1836 /* -------------------------------------------------------------------- */
1840 static PyMethodDef IDProp_methods[] = {
1841  {NULL, NULL, 0, NULL},
1842 };
1843 
1844 PyDoc_STRVAR(IDProp_module_doc,
1845  "This module provides access id property types (currently mainly for docs).");
1846 static struct PyModuleDef IDProp_module_def = {
1847  PyModuleDef_HEAD_INIT,
1848  "idprop", /* m_name */
1849  IDProp_module_doc, /* m_doc */
1850  0, /* m_size */
1851  IDProp_methods, /* m_methods */
1852  NULL, /* m_reload */
1853  NULL, /* m_traverse */
1854  NULL, /* m_clear */
1855  NULL, /* m_free */
1856 };
1857 
1858 PyObject *BPyInit_idprop(void)
1859 {
1860  PyObject *mod;
1861  PyObject *submodule;
1862  PyObject *sys_modules = PyImport_GetModuleDict();
1863 
1864  mod = PyModule_Create(&IDProp_module_def);
1865 
1866  /* idprop.types */
1867  PyModule_AddObject(mod, "types", (submodule = BPyInit_idprop_types()));
1868  PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
1869 
1870  return mod;
1871 }
1872 
typedef float(TangentPoint)[2]
#define IDP_Float(prop)
Definition: BKE_idprop.h:179
#define IDP_IDPArray(prop)
Definition: BKE_idprop.h:182
#define IDP_Int(prop)
Definition: BKE_idprop.h:154
void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item)
Definition: idprop.c:153
void IDP_FreePropertyContent(struct IDProperty *prop)
Definition: idprop.c:1029
struct IDProperty * IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:82
void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist)
Definition: idprop.c:557
#define IDP_String(prop)
Definition: BKE_idprop.h:181
#define IDP_Double(prop)
Definition: BKE_idprop.h:180
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1040
void IDP_ResizeArray(struct IDProperty *prop, int newlen)
Definition: idprop.c:232
struct IDProperty * IDP_GetPropertyFromGroup(const struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void IDP_MergeGroup(struct IDProperty *dest, const struct IDProperty *src, const bool do_overwrite) ATTR_NONNULL()
struct IDProperty * IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:907
void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL()
Definition: idprop.c:690
void IDP_ClearProperty(struct IDProperty *prop)
Definition: idprop.c:1046
#define IDP_Array(prop)
Definition: BKE_idprop.h:155
#define UNUSED(x)
#define UNLIKELY(x)
#define MIN2(a, b)
typedef double(DMatrix)[4][4]
ID and Library types, which are fundamental for sdna.
@ IDP_DOUBLE
Definition: DNA_ID.h:103
@ IDP_FLOAT
Definition: DNA_ID.h:99
@ IDP_STRING
Definition: DNA_ID.h:97
@ IDP_IDPARRAY
Definition: DNA_ID.h:104
@ IDP_INT
Definition: DNA_ID.h:98
@ IDP_GROUP
Definition: DNA_ID.h:101
@ IDP_ARRAY
Definition: DNA_ID.h:100
@ IDP_ID
Definition: DNA_ID.h:102
#define MAX_IDPROP_NAME
Definition: DNA_ID.h:92
@ IDP_STRING_SUB_UTF8
Definition: DNA_ID.h:124
@ IDP_STRING_SUB_BYTE
Definition: DNA_ID.h:125
static AppView * view
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
PyObject * self
Definition: bpy_driver.c:185
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
void IDProp_Init_Types(void)
static PyMethodDef IDProp_methods[]
PyDoc_STRVAR(BPy_IDGroup_pop_doc, ".. method:: pop(key, default)\n" "\n" " Remove an item from the group, returning a Python representation.\n" "\n" " :raises KeyError: When the item doesn't exist.\n" "\n" " :arg key: Name of item to remove.\n" " :type key: string\n" " :arg default: Value to return when key isn't found, otherwise raise an exception.\n" " :type default: Undefined\n")
static PyGetSetDef BPy_IDGroup_getseters[]
static struct PyModuleDef IDProp_module_def
static PyObject * BPy_IDGroup_pop(BPy_IDProperty *self, PyObject *args)
static PyObject * BPy_IDArray_slice(BPy_IDArray *self, int begin, int end)
static PyObject * BPy_IDGroup_get(BPy_IDProperty *self, PyObject *args)
static PyObject * BPy_IDGroup_keys(BPy_IDProperty *self)
static PyObject * BPyInit_idprop_types(void)
static struct PyMethodDef BPy_IDGroup_methods[]
static IDProperty * idp_from_PyBytes(const char *name, PyObject *ob)
bool pyrna_id_CheckPyObject(PyObject *obj)
Definition: bpy_rna.c:7633
static PyObject * BPy_IDArray_GetItem(BPy_IDArray *self, int index)
static PyGetSetDef BPy_IDArray_getseters[]
static PyObject * BPy_IDGroup_values(BPy_IDProperty *self)
int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val)
static void BPy_IDGroup_Iter_dealloc(BPy_IDGroup_Iter *self)
PyObject * BPy_IDGroup_MapDataToPy(IDProperty *prop)
static IDProperty * idp_from_PyLong(const char *name, PyObject *ob)
static PyMethodDef BPy_IDArray_methods[]
static IDProperty * idp_from_PyFloat(const char *name, PyObject *ob)
static PyObject * BPy_IDGroup_GetName(BPy_IDProperty *self, void *UNUSED(closure))
static int BPy_IDArray_ass_subscript(BPy_IDArray *self, PyObject *item, PyObject *value)
static const char * idp_format_from_array_type(int type)
static PyObject * BPy_IDArray_repr(BPy_IDArray *self)
PyObject * BPy_Wrap_GetItems(ID *id, IDProperty *prop)
static PyObject * BPy_IDArray_subscript(BPy_IDArray *self, PyObject *item)
static PyTypeObject * idp_array_py_type(BPy_IDArray *self, bool *r_is_double)
static PyObject * BPy_IDArray_to_list(BPy_IDArray *self)
static PyObject * BPy_IDGroup_repr(BPy_IDProperty *self)
static int itemsize_by_idarray_type(int array_type)
static PyObject * idprop_py_from_idp_double(const IDProperty *prop)
Definition: idprop_py_api.c:74
static const char * idp_try_read_name(PyObject *name_obj)
static PyObject * BPy_IDGroup_clear(BPy_IDProperty *self)
static void BPy_IDArray_releasebuffer(BPy_IDArray *UNUSED(self), Py_buffer *view)
PyTypeObject BPy_IDGroup_Type
bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob)
PyTypeObject BPy_IDArray_Type
PyObject * BPy_Wrap_GetValues(ID *id, IDProperty *prop)
static int BPy_IDGroup_Iter_clear(BPy_IDGroup_Iter *self)
static PyObject * idprop_py_from_idp_array(ID *id, IDProperty *prop)
Definition: idprop_py_api.c:93
PyTypeObject BPy_IDGroup_Iter_Type
static PySequenceMethods BPy_IDGroup_Seq
static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value)
PyObject * BPy_Wrap_GetKeys(IDProperty *prop)
static PyBufferProcs BPy_IDArray_Buffer
static PyObject * BPy_IDArray_get_typecode(BPy_IDArray *self)
static PyObject * idprop_py_from_idp_idparray(ID *id, IDProperty *prop)
static IDProperty * idp_from_PySequence(const char *name, PyObject *ob)
static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len, const char *func)
PyObject * BPy_IDGroup_WrapData(ID *id, IDProperty *prop, IDProperty *parent)
static PySequenceMethods BPy_IDArray_Seq
static PyObject * BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
static PyObject * BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item)
static IDProperty * idp_from_PyMapping(const char *name, PyObject *ob)
static PyMappingMethods BPy_IDArray_AsMapping
static IDProperty * idp_from_PyObject(PyObject *name_obj, PyObject *ob)
static IDProperty * idp_from_PySequence_Fast(const char *name, PyObject *ob)
PyObject * BPyInit_idprop(void)
static PyObject * idprop_py_from_idp_float(const IDProperty *prop)
Definition: idprop_py_api.c:69
static int BPy_IDArray_Len(BPy_IDArray *self)
static PyObject * idprop_py_from_idp_string(const IDProperty *prop)
Definition: idprop_py_api.c:51
static PyObject * IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
static PyObject * idprop_py_from_idp_group(ID *id, IDProperty *prop, IDProperty *parent)
Definition: idprop_py_api.c:79
static Py_ssize_t BPy_IDGroup_Map_Len(BPy_IDProperty *self)
static IDProperty * idp_from_PySequence_Buffer(const char *name, Py_buffer *buffer)
static char idp_sequence_type(PyObject *seq_fast)
static PyObject * idprop_py_from_idp_id(IDProperty *prop)
Definition: idprop_py_api.c:88
static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject *val)
PyObject * pyrna_id_CreatePyObject(ID *id)
Definition: bpy_rna.c:7611
static PyObject * BPy_IDGroup_items(BPy_IDProperty *self)
static PyObject * idprop_py_from_idp_int(const IDProperty *prop)
Definition: idprop_py_api.c:64
static int BPy_IDArray_ass_slice(BPy_IDArray *self, int begin, int end, PyObject *seq)
static struct PyModuleDef IDProp_types_module_def
bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
Definition: bpy_rna.c:7622
static PyObject * BPy_IDGroup_iter(BPy_IDProperty *self)
static int BPy_IDArray_getbuffer(BPy_IDArray *self, Py_buffer *view, int flags)
static PyObject * BPy_IDGroup_to_dict(BPy_IDProperty *self)
static PyObject * BPy_IDGroup_update(BPy_IDProperty *self, PyObject *value)
static Py_hash_t BPy_IDGroup_hash(BPy_IDProperty *self)
static int idp_array_type_from_formatstr_and_size(const char *typestr, Py_ssize_t itemsize)
static int BPy_IDGroup_Iter_traverse(BPy_IDGroup_Iter *self, visitproc visit, void *arg)
static IDProperty * idp_from_DatablockPointer(const char *name, PyObject *ob)
static IDProperty * idp_from_PyUnicode(const char *name, PyObject *ob)
static PyObject * BPy_IDGroup_iter_items(BPy_IDProperty *self)
static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUSED(closure))
static PyMappingMethods BPy_IDGroup_Mapping
#define IDPROP_ITER_KEYS
Definition: idprop_py_api.h:71
#define BPy_IDGroup_Check(v)
Definition: idprop_py_api.h:35
struct BPy_IDGroup_Iter BPy_IDGroup_Iter
struct BPy_IDProperty BPy_IDProperty
#define IDPROP_ITER_ITEMS
Definition: idprop_py_api.h:72
struct BPy_IDArray BPy_IDArray
int count
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static GPUContext * wrap(Context *ctx)
char PyC_StructFmt_type_from_str(const char *typestr)
const char * PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
PyObject * PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size)
bool PyC_StructFmt_type_is_int_any(char format)
const char * PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce)
bool PyC_StructFmt_type_is_float_any(char format)
int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length, const PyTypeObject *type, const bool is_double, const char *error_prefix)
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
struct IDProperty * cur
Definition: idprop_py_api.h:54
PyObject_VAR_HEAD BPy_IDProperty * group
Definition: idprop_py_api.h:53
struct IDProperty * parent
Definition: idprop_py_api.h:42
struct IDProperty * prop
Definition: idprop_py_api.h:41
PyObject_VAR_HEAD struct ID * id
Definition: idprop_py_api.h:40
ListBase group
Definition: DNA_ID.h:64
void * pointer
Definition: DNA_ID.h:63
short flag
Definition: DNA_ID.h:72
int len
Definition: DNA_ID.h:84
struct IDProperty * next
Definition: DNA_ID.h:70
char name[64]
Definition: DNA_ID.h:74
IDPropertyData data
Definition: DNA_ID.h:80
struct IDProperty * prev
Definition: DNA_ID.h:70
char subtype
Definition: DNA_ID.h:71
char type
Definition: DNA_ID.h:71
Definition: DNA_ID.h:273
void * first
Definition: DNA_listBase.h:47
const char * str
Definition: BKE_idprop.h:41
struct IDPropertyTemplate::@28 array
struct ID * id
Definition: BKE_idprop.h:45
struct IDPropertyTemplate::@27 string
ccl_device_inline int mod(int x, int m)
Definition: util_math.h:405
uint len