Cleanup: misc spelling fixes
[blender.git] / source / blender / python / intern / bpy_rna.c
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
17 /** \file
18  * \ingroup pythonintern
19  *
20  * This file is the main interface between Python and Blender's data api (RNA),
21  * exposing RNA to Python so blender data can be accessed in a Python like way.
22  *
23  * The two main types are #BPy_StructRNA and #BPy_PropertyRNA - the base
24  * classes for most of the data Python accesses in blender.
25  */
26
27 #include <Python.h>
28
29 #include <stddef.h>
30 #include <float.h> /* FLT_MIN/MAX */
31
32 #include "RNA_types.h"
33
34 #include "BLI_bitmap.h"
35 #include "BLI_dynstr.h"
36 #include "BLI_string.h"
37 #include "BLI_listbase.h"
38 #include "BLI_math_rotation.h"
39 #include "BLI_utildefines.h"
40
41 #include "BPY_extern.h"
42 #include "BPY_extern_clog.h"
43
44 #include "bpy_rna.h"
45 #include "bpy_rna_anim.h"
46 #include "bpy_props.h"
47 #include "bpy_capi_utils.h"
48 #include "bpy_rna_callback.h"
49 #include "bpy_intern_string.h"
50
51 #ifdef USE_PYRNA_INVALIDATE_WEAKREF
52 #  include "BLI_ghash.h"
53 #endif
54
55 #include "RNA_enum_types.h"
56 #include "RNA_define.h" /* RNA_def_property_free_identifier */
57 #include "RNA_access.h"
58
59 #include "CLG_log.h"
60
61 #include "MEM_guardedalloc.h"
62
63 #include "BKE_main.h"
64 #include "BKE_idcode.h"
65 #include "BKE_context.h"
66 #include "BKE_global.h" /* evil G.* */
67 #include "BKE_report.h"
68 #include "BKE_idprop.h"
69
70 /* Only for types. */
71 #include "BKE_node.h"
72
73 #include "../generic/idprop_py_api.h" /* For IDprop lookups. */
74 #include "../generic/py_capi_utils.h"
75 #include "../generic/python_utildefines.h"
76
77 #define USE_PEDANTIC_WRITE
78 #define USE_MATHUTILS
79 #define USE_STRING_COERCE
80
81 BPy_StructRNA *bpy_context_module = NULL; /* for fast access */
82
83 static PyObject *pyrna_struct_Subtype(PointerRNA *ptr);
84 static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self);
85
86 #define BPY_DOC_ID_PROP_TYPE_NOTE \
87   "   .. note::\n" \
88   "\n" \
89   "      Only the :class:`bpy.types.ID`, :class:`bpy.types.Bone` and\n" \
90   "      :class:`bpy.types.PoseBone` classes support custom properties.\n"
91
92 int pyrna_struct_validity_check(BPy_StructRNA *pysrna)
93 {
94   if (pysrna->ptr.type) {
95     return 0;
96   }
97   PyErr_Format(
98       PyExc_ReferenceError, "StructRNA of type %.200s has been removed", Py_TYPE(pysrna)->tp_name);
99   return -1;
100 }
101
102 int pyrna_prop_validity_check(BPy_PropertyRNA *self)
103 {
104   if (self->ptr.type) {
105     return 0;
106   }
107   PyErr_Format(PyExc_ReferenceError,
108                "PropertyRNA of type %.200s.%.200s has been removed",
109                Py_TYPE(self)->tp_name,
110                RNA_property_identifier(self->prop));
111   return -1;
112 }
113
114 void pyrna_invalidate(BPy_DummyPointerRNA *self)
115 {
116   RNA_POINTER_INVALIDATE(&self->ptr);
117 }
118
119 #ifdef USE_PYRNA_INVALIDATE_GC
120 #  define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g) + 1))
121
122 /* Only for sizeof(). */
123 struct gc_generation {
124   PyGC_Head head;
125   int threshold;
126   int count;
127 } gc_generation;
128
129 static void id_release_gc(struct ID *id)
130 {
131   unsigned int j;
132   // unsigned int i = 0;
133   for (j = 0; j < 3; j++) {
134     /* Hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed. */
135     PyGC_Head *gen = (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j));
136     PyGC_Head *g = gen->gc.gc_next;
137     while ((g = g->gc.gc_next) != gen) {
138       PyObject *ob = FROM_GC(g);
139       if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) ||
140           PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) {
141         BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob;
142         if (ob_ptr->ptr.id.data == id) {
143           pyrna_invalidate(ob_ptr);
144           // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name);
145           // i++;
146         }
147       }
148     }
149   }
150   // printf("id_release_gc freed '%s': %d\n", id->name, i);
151 }
152 #endif
153
154 #ifdef USE_PYRNA_INVALIDATE_WEAKREF
155 //#define DEBUG_RNA_WEAKREF
156
157 struct GHash *id_weakref_pool = NULL;
158 static PyObject *id_free_weakref_cb(PyObject *weakinfo_pair, PyObject *weakref);
159 static PyMethodDef id_free_weakref_cb_def = {
160     "id_free_weakref_cb", (PyCFunction)id_free_weakref_cb, METH_O, NULL};
161
162 /* Adds a reference to the list, remember to decref. */
163 static GHash *id_weakref_pool_get(ID *id)
164 {
165   GHash *weakinfo_hash = NULL;
166
167   if (id_weakref_pool) {
168     weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id);
169   }
170   else {
171     /* First time, allocate pool. */
172     id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool");
173     weakinfo_hash = NULL;
174   }
175
176   if (weakinfo_hash == NULL) {
177     /* We use a ghash as a set, we could use libHX's HXMAP_SINGULAR, but would be an extra dep. */
178     weakinfo_hash = BLI_ghash_ptr_new("rna_id");
179     BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash);
180   }
181
182   return weakinfo_hash;
183 }
184
185 /* Called from pyrna_struct_CreatePyObject() and pyrna_prop_CreatePyObject(). */
186 static void id_weakref_pool_add(ID *id, BPy_DummyPointerRNA *pyrna)
187 {
188   PyObject *weakref;
189   PyObject *weakref_capsule;
190   PyObject *weakref_cb_py;
191
192   /* Create a new function instance and insert the list as 'self'
193    * so we can remove ourself from it. */
194   GHash *weakinfo_hash = id_weakref_pool_get(id); /* New or existing. */
195
196   weakref_capsule = PyCapsule_New(weakinfo_hash, NULL, NULL);
197   weakref_cb_py = PyCFunction_New(&id_free_weakref_cb_def, weakref_capsule);
198   Py_DECREF(weakref_capsule);
199
200   /* Add weakref to weakinfo_hash list. */
201   weakref = PyWeakref_NewRef((PyObject *)pyrna, weakref_cb_py);
202
203   Py_DECREF(weakref_cb_py); /* Function owned by the weakref now. */
204
205   /* Important to add at the end of the hash, since first removal looks at the end. */
206
207   /* Using a hash table as a set, all 'id's are the same. */
208   BLI_ghash_insert(weakinfo_hash, weakref, id);
209   /* weakinfo_hash owns the weakref */
210 }
211
212 /* Workaround to get the last id without a lookup. */
213 static ID *_id_tmp_ptr;
214 static void value_id_set(void *id)
215 {
216   _id_tmp_ptr = (ID *)id;
217 }
218
219 static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash);
220 static PyObject *id_free_weakref_cb(PyObject *weakinfo_capsule, PyObject *weakref)
221 {
222   /* Important to search backwards. */
223   GHash *weakinfo_hash = PyCapsule_GetPointer(weakinfo_capsule, NULL);
224
225   if (BLI_ghash_len(weakinfo_hash) > 1) {
226     BLI_ghash_remove(weakinfo_hash, weakref, NULL, NULL);
227   }
228   else { /* Get the last id and free it. */
229     BLI_ghash_remove(weakinfo_hash, weakref, NULL, value_id_set);
230     id_release_weakref_list(_id_tmp_ptr, weakinfo_hash);
231   }
232
233   Py_DECREF(weakref);
234
235   Py_RETURN_NONE;
236 }
237
238 static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash)
239 {
240   GHashIterator weakinfo_hash_iter;
241
242   BLI_ghashIterator_init(&weakinfo_hash_iter, weakinfo_hash);
243
244 #  ifdef DEBUG_RNA_WEAKREF
245   fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_len(weakinfo_hash));
246 #  endif
247
248   while (!BLI_ghashIterator_done(&weakinfo_hash_iter)) {
249     PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter);
250     PyObject *item = PyWeakref_GET_OBJECT(weakref);
251     if (item != Py_None) {
252
253 #  ifdef DEBUG_RNA_WEAKREF
254       PyC_ObSpit("id_release_weakref item ", item);
255 #  endif
256
257       pyrna_invalidate((BPy_DummyPointerRNA *)item);
258     }
259
260     Py_DECREF(weakref);
261
262     BLI_ghashIterator_step(&weakinfo_hash_iter);
263   }
264
265   BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL);
266   BLI_ghash_free(weakinfo_hash, NULL, NULL);
267
268   if (BLI_ghash_len(id_weakref_pool) == 0) {
269     BLI_ghash_free(id_weakref_pool, NULL, NULL);
270     id_weakref_pool = NULL;
271 #  ifdef DEBUG_RNA_WEAKREF
272     printf("id_release_weakref freeing pool\n");
273 #  endif
274   }
275 }
276
277 static void id_release_weakref(struct ID *id)
278 {
279   GHash *weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id);
280   if (weakinfo_hash) {
281     id_release_weakref_list(id, weakinfo_hash);
282   }
283 }
284
285 #endif /* USE_PYRNA_INVALIDATE_WEAKREF */
286
287 void BPY_id_release(struct ID *id)
288 {
289 #ifdef USE_PYRNA_INVALIDATE_GC
290   id_release_gc(id);
291 #endif
292
293 #ifdef USE_PYRNA_INVALIDATE_WEAKREF
294   if (id_weakref_pool) {
295     PyGILState_STATE gilstate = PyGILState_Ensure();
296
297     id_release_weakref(id);
298
299     PyGILState_Release(gilstate);
300   }
301 #endif /* USE_PYRNA_INVALIDATE_WEAKREF */
302
303   (void)id;
304 }
305
306 #ifdef USE_PEDANTIC_WRITE
307 static bool rna_disallow_writes = false;
308
309 static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
310 {
311   ID *id = ptr->id.data;
312   if (id) {
313     const short idcode = GS(id->name);
314     /* May need more ID types added here. */
315     if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) {
316       const char *idtype = BKE_idcode_to_name(idcode);
317       const char *pyname;
318       if (key && PyUnicode_Check(key)) {
319         pyname = _PyUnicode_AsString(key);
320       }
321       else {
322         pyname = "<UNKNOWN>";
323       }
324
325       /* Make a nice string error. */
326       BLI_assert(idtype != NULL);
327       PyErr_Format(PyExc_AttributeError,
328                    "Writing to ID classes in this context is not allowed: "
329                    "%.200s, %.200s datablock, error setting %.200s.%.200s",
330                    id->name + 2,
331                    idtype,
332                    RNA_struct_identifier(ptr->type),
333                    pyname);
334
335       return true;
336     }
337   }
338   return false;
339 }
340 #endif /* USE_PEDANTIC_WRITE */
341
342 #ifdef USE_PEDANTIC_WRITE
343 bool pyrna_write_check(void)
344 {
345   return !rna_disallow_writes;
346 }
347
348 void pyrna_write_set(bool val)
349 {
350   rna_disallow_writes = !val;
351 }
352 #else  /* USE_PEDANTIC_WRITE */
353 bool pyrna_write_check(void)
354 {
355   return true;
356 }
357 void pyrna_write_set(bool UNUSED(val))
358 {
359   /* pass */
360 }
361 #endif /* USE_PEDANTIC_WRITE */
362
363 static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self);
364 static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self);
365 static int pyrna_py_to_prop(
366     PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix);
367 static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item);
368
369 #ifdef USE_MATHUTILS
370 #  include "../mathutils/mathutils.h" /* So we can have mathutils callbacks. */
371
372 static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self,
373                                                   PointerRNA *ptr,
374                                                   PropertyRNA *prop,
375                                                   Py_ssize_t start,
376                                                   Py_ssize_t stop,
377                                                   Py_ssize_t length);
378 static short pyrna_rotation_euler_order_get(PointerRNA *ptr,
379                                             const short order_fallback,
380                                             PropertyRNA **r_prop_eul_order);
381
382 /* bpyrna vector/euler/quat callbacks. */
383 static unsigned char mathutils_rna_array_cb_index = -1; /* Index for our callbacks. */
384
385 /* Subtype not used much yet. */
386 #  define MATHUTILS_CB_SUBTYPE_EUL 0
387 #  define MATHUTILS_CB_SUBTYPE_VEC 1
388 #  define MATHUTILS_CB_SUBTYPE_QUAT 2
389 #  define MATHUTILS_CB_SUBTYPE_COLOR 3
390
391 static int mathutils_rna_generic_check(BaseMathObject *bmo)
392 {
393   BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
394
395   PYRNA_PROP_CHECK_INT(self);
396
397   return self->prop ? 0 : -1;
398 }
399
400 static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype)
401 {
402   BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
403
404   PYRNA_PROP_CHECK_INT(self);
405
406   if (self->prop == NULL) {
407     return -1;
408   }
409
410   RNA_property_float_get_array(&self->ptr, self->prop, bmo->data);
411
412   /* Euler order exception. */
413   if (subtype == MATHUTILS_CB_SUBTYPE_EUL) {
414     EulerObject *eul = (EulerObject *)bmo;
415     PropertyRNA *prop_eul_order = NULL;
416     eul->order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order);
417   }
418
419   return 0;
420 }
421
422 static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype)
423 {
424   BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
425   float min, max;
426
427   PYRNA_PROP_CHECK_INT(self);
428
429   if (self->prop == NULL) {
430     return -1;
431   }
432
433 #  ifdef USE_PEDANTIC_WRITE
434   if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) {
435     return -1;
436   }
437 #  endif /* USE_PEDANTIC_WRITE */
438
439   if (!RNA_property_editable_flag(&self->ptr, self->prop)) {
440     PyErr_Format(PyExc_AttributeError,
441                  "bpy_prop \"%.200s.%.200s\" is read-only",
442                  RNA_struct_identifier(self->ptr.type),
443                  RNA_property_identifier(self->prop));
444     return -1;
445   }
446
447   RNA_property_float_range(&self->ptr, self->prop, &min, &max);
448
449   if (min != -FLT_MAX || max != FLT_MAX) {
450     int i, len = RNA_property_array_length(&self->ptr, self->prop);
451     for (i = 0; i < len; i++) {
452       CLAMP(bmo->data[i], min, max);
453     }
454   }
455
456   RNA_property_float_set_array(&self->ptr, self->prop, bmo->data);
457   if (RNA_property_update_check(self->prop)) {
458     RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
459   }
460
461   /* Euler order exception. */
462   if (subtype == MATHUTILS_CB_SUBTYPE_EUL) {
463     EulerObject *eul = (EulerObject *)bmo;
464     PropertyRNA *prop_eul_order = NULL;
465     short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order);
466     if (order != eul->order) {
467       RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order);
468       if (RNA_property_update_check(prop_eul_order)) {
469         RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order);
470       }
471     }
472   }
473   return 0;
474 }
475
476 static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int UNUSED(subtype), int index)
477 {
478   BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
479
480   PYRNA_PROP_CHECK_INT(self);
481
482   if (self->prop == NULL) {
483     return -1;
484   }
485
486   bmo->data[index] = RNA_property_float_get_index(&self->ptr, self->prop, index);
487   return 0;
488 }
489
490 static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int UNUSED(subtype), int index)
491 {
492   BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
493
494   PYRNA_PROP_CHECK_INT(self);
495
496   if (self->prop == NULL) {
497     return -1;
498   }
499
500 #  ifdef USE_PEDANTIC_WRITE
501   if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) {
502     return -1;
503   }
504 #  endif /* USE_PEDANTIC_WRITE */
505
506   if (!RNA_property_editable_flag(&self->ptr, self->prop)) {
507     PyErr_Format(PyExc_AttributeError,
508                  "bpy_prop \"%.200s.%.200s\" is read-only",
509                  RNA_struct_identifier(self->ptr.type),
510                  RNA_property_identifier(self->prop));
511     return -1;
512   }
513
514   RNA_property_float_clamp(&self->ptr, self->prop, &bmo->data[index]);
515   RNA_property_float_set_index(&self->ptr, self->prop, index, bmo->data[index]);
516
517   if (RNA_property_update_check(self->prop)) {
518     RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
519   }
520
521   return 0;
522 }
523
524 static Mathutils_Callback mathutils_rna_array_cb = {
525     (BaseMathCheckFunc)mathutils_rna_generic_check,
526     (BaseMathGetFunc)mathutils_rna_vector_get,
527     (BaseMathSetFunc)mathutils_rna_vector_set,
528     (BaseMathGetIndexFunc)mathutils_rna_vector_get_index,
529     (BaseMathSetIndexFunc)mathutils_rna_vector_set_index,
530 };
531
532 /* bpyrna matrix callbacks */
533 static unsigned char mathutils_rna_matrix_cb_index = -1; /* Index for our callbacks. */
534
535 static int mathutils_rna_matrix_get(BaseMathObject *bmo, int UNUSED(subtype))
536 {
537   BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
538
539   PYRNA_PROP_CHECK_INT(self);
540
541   if (self->prop == NULL) {
542     return -1;
543   }
544
545   RNA_property_float_get_array(&self->ptr, self->prop, bmo->data);
546   return 0;
547 }
548
549 static int mathutils_rna_matrix_set(BaseMathObject *bmo, int UNUSED(subtype))
550 {
551   BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
552
553   PYRNA_PROP_CHECK_INT(self);
554
555   if (self->prop == NULL) {
556     return -1;
557   }
558
559 #  ifdef USE_PEDANTIC_WRITE
560   if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) {
561     return -1;
562   }
563 #  endif /* USE_PEDANTIC_WRITE */
564
565   if (!RNA_property_editable_flag(&self->ptr, self->prop)) {
566     PyErr_Format(PyExc_AttributeError,
567                  "bpy_prop \"%.200s.%.200s\" is read-only",
568                  RNA_struct_identifier(self->ptr.type),
569                  RNA_property_identifier(self->prop));
570     return -1;
571   }
572
573   /* Can ignore clamping here. */
574   RNA_property_float_set_array(&self->ptr, self->prop, bmo->data);
575
576   if (RNA_property_update_check(self->prop)) {
577     RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
578   }
579   return 0;
580 }
581
582 static Mathutils_Callback mathutils_rna_matrix_cb = {
583     mathutils_rna_generic_check,
584     mathutils_rna_matrix_get,
585     mathutils_rna_matrix_set,
586     NULL,
587     NULL,
588 };
589
590 static short pyrna_rotation_euler_order_get(PointerRNA *ptr,
591                                             const short order_fallback,
592                                             PropertyRNA **r_prop_eul_order)
593 {
594   /* Attempt to get order. */
595   if (*r_prop_eul_order == NULL) {
596     *r_prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode");
597   }
598
599   if (*r_prop_eul_order) {
600     short order = RNA_property_enum_get(ptr, *r_prop_eul_order);
601     /* Could be quat or axisangle. */
602     if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) {
603       return order;
604     }
605   }
606
607   return order_fallback;
608 }
609
610 #endif /* USE_MATHUTILS */
611
612 /**
613  * Note that #PROP_NONE is included as a vector subtype. this is because it is handy to
614  * have x/y access to fcurve keyframes and other fixed size float arrays of length 2-4.
615  */
616 #define PROP_ALL_VECTOR_SUBTYPES \
617   PROP_COORDS: \
618   case PROP_TRANSLATION: \
619   case PROP_DIRECTION: \
620   case PROP_VELOCITY: \
621   case PROP_ACCELERATION: \
622   case PROP_XYZ: \
623   case PROP_XYZ_LENGTH
624
625 PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
626 {
627   PyObject *ret = NULL;
628
629 #ifdef USE_MATHUTILS
630   int subtype, totdim;
631   int len;
632   const int flag = RNA_property_flag(prop);
633   const int type = RNA_property_type(prop);
634   const bool is_thick = (flag & PROP_THICK_WRAP) != 0;
635
636   /* disallow dynamic sized arrays to be wrapped since the size could change
637    * to a size mathutils does not support */
638   if (flag & PROP_DYNAMIC) {
639     return NULL;
640   }
641
642   len = RNA_property_array_length(ptr, prop);
643   if (type == PROP_FLOAT) {
644     /* pass */
645   }
646   else if (type == PROP_INT) {
647     if (is_thick) {
648       goto thick_wrap_slice;
649     }
650     else {
651       return NULL;
652     }
653   }
654   else {
655     return NULL;
656   }
657
658   subtype = RNA_property_subtype(prop);
659   totdim = RNA_property_array_dimension(ptr, prop, NULL);
660
661   if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) {
662     if (!is_thick) {
663       /* Owned by the mathutils PyObject. */
664       ret = pyrna_prop_CreatePyObject(ptr, prop);
665     }
666
667     switch (subtype) {
668       case PROP_ALL_VECTOR_SUBTYPES:
669         if (len >= 2 && len <= 4) {
670           if (is_thick) {
671             ret = Vector_CreatePyObject(NULL, len, NULL);
672             RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec);
673           }
674           else {
675             PyObject *vec_cb = Vector_CreatePyObject_cb(
676                 ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC);
677             Py_DECREF(ret); /* The vector owns 'ret' now. */
678             ret = vec_cb;   /* Return the vector instead. */
679           }
680         }
681         break;
682       case PROP_MATRIX:
683         if (len == 16) {
684           if (is_thick) {
685             ret = Matrix_CreatePyObject(NULL, 4, 4, NULL);
686             RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
687           }
688           else {
689             PyObject *mat_cb = Matrix_CreatePyObject_cb(
690                 ret, 4, 4, mathutils_rna_matrix_cb_index, 0);
691             Py_DECREF(ret); /* The matrix owns 'ret' now. */
692             ret = mat_cb;   /* Return the matrix instead. */
693           }
694         }
695         else if (len == 9) {
696           if (is_thick) {
697             ret = Matrix_CreatePyObject(NULL, 3, 3, NULL);
698             RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
699           }
700           else {
701             PyObject *mat_cb = Matrix_CreatePyObject_cb(
702                 ret, 3, 3, mathutils_rna_matrix_cb_index, 0);
703             Py_DECREF(ret); /* The matrix owns 'ret' now. */
704             ret = mat_cb;   /* Return the matrix instead. */
705           }
706         }
707         break;
708       case PROP_EULER:
709       case PROP_QUATERNION:
710         if (len == 3) { /* Euler. */
711           if (is_thick) {
712             /* Attempt to get order,
713              * only needed for thick types since wrapped with update via callbacks. */
714             PropertyRNA *prop_eul_order = NULL;
715             short order = pyrna_rotation_euler_order_get(ptr, EULER_ORDER_XYZ, &prop_eul_order);
716
717             ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA. */
718             RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul);
719           }
720           else {
721             /* Order will be updated from callback on use. */
722             // TODO, get order from RNA
723             PyObject *eul_cb = Euler_CreatePyObject_cb(
724                 ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL);
725             Py_DECREF(ret); /* The euler owns 'ret' now. */
726             ret = eul_cb;   /* Return the euler instead. */
727           }
728         }
729         else if (len == 4) {
730           if (is_thick) {
731             ret = Quaternion_CreatePyObject(NULL, NULL);
732             RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat);
733           }
734           else {
735             PyObject *quat_cb = Quaternion_CreatePyObject_cb(
736                 ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT);
737             Py_DECREF(ret); /* The quat owns 'ret' now. */
738             ret = quat_cb;  /* Return the quat instead. */
739           }
740         }
741         break;
742       case PROP_COLOR:
743       case PROP_COLOR_GAMMA:
744         if (len == 3) { /* Color. */
745           if (is_thick) {
746             ret = Color_CreatePyObject(NULL, NULL);
747             RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col);
748           }
749           else {
750             PyObject *col_cb = Color_CreatePyObject_cb(
751                 ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_COLOR);
752             Py_DECREF(ret); /* The color owns 'ret' now. */
753             ret = col_cb;   /* Return the color instead. */
754           }
755         }
756         break;
757       default:
758         break;
759     }
760   }
761
762   if (ret == NULL) {
763     if (is_thick) {
764       /* This is an array we can't reference (since it is not thin wrappable)
765        * and cannot be coerced into a mathutils type, so return as a list. */
766     thick_wrap_slice:
767       ret = pyrna_prop_array_subscript_slice(NULL, ptr, prop, 0, len, len);
768     }
769     else {
770       ret = pyrna_prop_CreatePyObject(ptr, prop); /* Owned by the mathutils PyObject. */
771     }
772   }
773 #else  /* USE_MATHUTILS */
774   (void)ptr;
775   (void)prop;
776 #endif /* USE_MATHUTILS */
777
778   return ret;
779 }
780
781 /**
782  * Same as #RNA_enum_value_from_id, but raises an exception.
783  */
784 int pyrna_enum_value_from_id(const EnumPropertyItem *item,
785                              const char *identifier,
786                              int *r_value,
787                              const char *error_prefix)
788 {
789   if (RNA_enum_value_from_id(item, identifier, r_value) == 0) {
790     const char *enum_str = BPy_enum_as_string(item);
791     PyErr_Format(
792         PyExc_ValueError, "%s: '%.200s' not found in (%s)", error_prefix, identifier, enum_str);
793     MEM_freeN((void *)enum_str);
794     return -1;
795   }
796
797   return 0;
798 }
799
800 /* note on __cmp__:
801  * checking the 'ptr->data' matches works in almost all cases,
802  * however there are a few RNA properties that are fake sub-structs and
803  * share the pointer with the parent, in those cases this happens 'a.b == a'
804  * see: r43352 for example.
805  *
806  * So compare the 'ptr->type' as well to avoid this problem.
807  * It's highly unlikely this would happen that 'ptr->data' and 'ptr->prop' would match,
808  * but _not_ 'ptr->type' but include this check for completeness.
809  * - campbell */
810
811 static int pyrna_struct_compare(BPy_StructRNA *a, BPy_StructRNA *b)
812 {
813   return (((a->ptr.data == b->ptr.data) && (a->ptr.type == b->ptr.type)) ? 0 : -1);
814 }
815
816 static int pyrna_prop_compare(BPy_PropertyRNA *a, BPy_PropertyRNA *b)
817 {
818   return (((a->prop == b->prop) && (a->ptr.data == b->ptr.data) && (a->ptr.type == b->ptr.type)) ?
819               0 :
820               -1);
821 }
822
823 static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op)
824 {
825   PyObject *res;
826   int ok = -1; /* Zero is true. */
827
828   if (BPy_StructRNA_Check(a) && BPy_StructRNA_Check(b)) {
829     ok = pyrna_struct_compare((BPy_StructRNA *)a, (BPy_StructRNA *)b);
830   }
831
832   switch (op) {
833     case Py_NE:
834       ok = !ok;
835       ATTR_FALLTHROUGH;
836     case Py_EQ:
837       res = ok ? Py_False : Py_True;
838       break;
839
840     case Py_LT:
841     case Py_LE:
842     case Py_GT:
843     case Py_GE:
844       res = Py_NotImplemented;
845       break;
846     default:
847       PyErr_BadArgument();
848       return NULL;
849   }
850
851   return Py_INCREF_RET(res);
852 }
853
854 static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
855 {
856   PyObject *res;
857   int ok = -1; /* Zero is true. */
858
859   if (BPy_PropertyRNA_Check(a) && BPy_PropertyRNA_Check(b)) {
860     ok = pyrna_prop_compare((BPy_PropertyRNA *)a, (BPy_PropertyRNA *)b);
861   }
862
863   switch (op) {
864     case Py_NE:
865       ok = !ok;
866       ATTR_FALLTHROUGH;
867     case Py_EQ:
868       res = ok ? Py_False : Py_True;
869       break;
870
871     case Py_LT:
872     case Py_LE:
873     case Py_GT:
874     case Py_GE:
875       res = Py_NotImplemented;
876       break;
877     default:
878       PyErr_BadArgument();
879       return NULL;
880   }
881
882   return Py_INCREF_RET(res);
883 }
884
885 /*----------------------repr--------------------------------------------*/
886 static PyObject *pyrna_struct_str(BPy_StructRNA *self)
887 {
888   PyObject *ret;
889   const char *name;
890
891   if (!PYRNA_STRUCT_IS_VALID(self)) {
892     return PyUnicode_FromFormat("<bpy_struct, %.200s invalid>", Py_TYPE(self)->tp_name);
893   }
894
895   /* Print name if available. */
896   name = RNA_struct_name_get_alloc(&self->ptr, NULL, 0, NULL);
897   if (name) {
898     ret = PyUnicode_FromFormat(
899         "<bpy_struct, %.200s(\"%.200s\")>", RNA_struct_identifier(self->ptr.type), name);
900     MEM_freeN((void *)name);
901     return ret;
902   }
903
904   return PyUnicode_FromFormat(
905       "<bpy_struct, %.200s at %p>", RNA_struct_identifier(self->ptr.type), self->ptr.data);
906 }
907
908 static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
909 {
910   ID *id = self->ptr.id.data;
911   PyObject *tmp_str;
912   PyObject *ret;
913
914   if (id == NULL || !PYRNA_STRUCT_IS_VALID(self)) {
915     /* fallback */
916     return pyrna_struct_str(self);
917   }
918
919   tmp_str = PyUnicode_FromString(id->name + 2);
920
921   if (RNA_struct_is_ID(self->ptr.type)) {
922     ret = PyUnicode_FromFormat(
923         "bpy.data.%s[%R]", BKE_idcode_to_name_plural(GS(id->name)), tmp_str);
924   }
925   else {
926     const char *path;
927     path = RNA_path_from_ID_to_struct(&self->ptr);
928     if (path) {
929       if (GS(id->name) == ID_NT) { /* Nodetree paths are not accurate. */
930         ret = PyUnicode_FromFormat("bpy.data...%s", path);
931       }
932       else {
933         ret = PyUnicode_FromFormat(
934             "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(id->name)), tmp_str, path);
935       }
936
937       MEM_freeN((void *)path);
938     }
939     else {
940       /* Can't find the path, print something useful as a fallback. */
941       ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s",
942                                  BKE_idcode_to_name_plural(GS(id->name)),
943                                  tmp_str,
944                                  RNA_struct_identifier(self->ptr.type));
945     }
946   }
947
948   Py_DECREF(tmp_str);
949
950   return ret;
951 }
952
953 static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
954 {
955   PyObject *ret;
956   PointerRNA ptr;
957   const char *name;
958   const char *type_id = NULL;
959   char type_fmt[64] = "";
960   int type;
961
962   PYRNA_PROP_CHECK_OBJ(self);
963
964   type = RNA_property_type(self->prop);
965
966   if (RNA_enum_id_from_value(rna_enum_property_type_items, type, &type_id) == 0) {
967     /* Should never happen. */
968     PyErr_SetString(PyExc_RuntimeError, "could not use property type, internal error");
969     return NULL;
970   }
971   else {
972     /* This should never fail. */
973     int len = -1;
974     char *c = type_fmt;
975
976     while ((*c++ = tolower(*type_id++))) {
977     }
978
979     if (type == PROP_COLLECTION) {
980       len = pyrna_prop_collection_length(self);
981     }
982     else if (RNA_property_array_check(self->prop)) {
983       len = pyrna_prop_array_length((BPy_PropertyArrayRNA *)self);
984     }
985
986     if (len != -1) {
987       sprintf(--c, "[%d]", len);
988     }
989   }
990
991   /* If a pointer, try to print name of pointer target too. */
992   if (type == PROP_POINTER) {
993     ptr = RNA_property_pointer_get(&self->ptr, self->prop);
994     name = RNA_struct_name_get_alloc(&ptr, NULL, 0, NULL);
995
996     if (name) {
997       ret = PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>",
998                                  type_fmt,
999                                  RNA_struct_identifier(self->ptr.type),
1000                                  RNA_property_identifier(self->prop),
1001                                  name);
1002       MEM_freeN((void *)name);
1003       return ret;
1004     }
1005   }
1006   if (type == PROP_COLLECTION) {
1007     PointerRNA r_ptr;
1008     if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) {
1009       return PyUnicode_FromFormat(
1010           "<bpy_%.200s, %.200s>", type_fmt, RNA_struct_identifier(r_ptr.type));
1011     }
1012   }
1013
1014   return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>",
1015                               type_fmt,
1016                               RNA_struct_identifier(self->ptr.type),
1017                               RNA_property_identifier(self->prop));
1018 }
1019
1020 static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, const int index)
1021 {
1022   ID *id = self->ptr.id.data;
1023   PyObject *tmp_str;
1024   PyObject *ret;
1025   const char *path;
1026
1027   PYRNA_PROP_CHECK_OBJ(self);
1028
1029   if (id == NULL) {
1030     /* Fallback. */
1031     return pyrna_prop_str(self);
1032   }
1033
1034   tmp_str = PyUnicode_FromString(id->name + 2);
1035
1036   path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index);
1037
1038   if (path) {
1039     const char *data_delim = (path[0] == '[') ? "" : ".";
1040     if (GS(id->name) == ID_NT) { /* Nodetree paths are not accurate. */
1041       ret = PyUnicode_FromFormat("bpy.data...%s", path);
1042     }
1043     else {
1044       ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s",
1045                                  BKE_idcode_to_name_plural(GS(id->name)),
1046                                  tmp_str,
1047                                  data_delim,
1048                                  path);
1049     }
1050
1051     MEM_freeN((void *)path);
1052   }
1053   else {
1054     /* Can't find the path, print something useful as a fallback. */
1055     ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s",
1056                                BKE_idcode_to_name_plural(GS(id->name)),
1057                                tmp_str,
1058                                RNA_property_identifier(self->prop));
1059   }
1060
1061   Py_DECREF(tmp_str);
1062
1063   return ret;
1064 }
1065
1066 static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
1067 {
1068   return pyrna_prop_repr_ex(self, 0, -1);
1069 }
1070
1071 static PyObject *pyrna_prop_array_repr(BPy_PropertyArrayRNA *self)
1072 {
1073   return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset);
1074 }
1075
1076 static PyObject *pyrna_func_repr(BPy_FunctionRNA *self)
1077 {
1078   return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>",
1079                               Py_TYPE(self)->tp_name,
1080                               RNA_struct_identifier(self->ptr.type),
1081                               RNA_function_identifier(self->func));
1082 }
1083
1084 static Py_hash_t pyrna_struct_hash(BPy_StructRNA *self)
1085 {
1086   return _Py_HashPointer(self->ptr.data);
1087 }
1088
1089 /* From Python's meth_hash v3.1.2. */
1090 static long pyrna_prop_hash(BPy_PropertyRNA *self)
1091 {
1092   long x, y;
1093   if (self->ptr.data == NULL) {
1094     x = 0;
1095   }
1096   else {
1097     x = _Py_HashPointer(self->ptr.data);
1098     if (x == -1) {
1099       return -1;
1100     }
1101   }
1102   y = _Py_HashPointer((void *)(self->prop));
1103   if (y == -1) {
1104     return -1;
1105   }
1106   x ^= y;
1107   if (x == -1) {
1108     x = -2;
1109   }
1110   return x;
1111 }
1112
1113 #ifdef USE_PYRNA_STRUCT_REFERENCE
1114 static int pyrna_struct_traverse(BPy_StructRNA *self, visitproc visit, void *arg)
1115 {
1116   Py_VISIT(self->reference);
1117   return 0;
1118 }
1119
1120 static int pyrna_struct_clear(BPy_StructRNA *self)
1121 {
1122   Py_CLEAR(self->reference);
1123   return 0;
1124 }
1125 #endif /* !USE_PYRNA_STRUCT_REFERENCE */
1126
1127 /* Use our own dealloc so we can free a property if we use one. */
1128 static void pyrna_struct_dealloc(BPy_StructRNA *self)
1129 {
1130 #ifdef PYRNA_FREE_SUPPORT
1131   if (self->freeptr && self->ptr.data) {
1132     IDP_FreeProperty(self->ptr.data);
1133     self->ptr.data = NULL;
1134   }
1135 #endif /* PYRNA_FREE_SUPPORT */
1136
1137 #ifdef USE_WEAKREFS
1138   if (self->in_weakreflist != NULL) {
1139     PyObject_ClearWeakRefs((PyObject *)self);
1140   }
1141 #endif
1142
1143 #ifdef USE_PYRNA_STRUCT_REFERENCE
1144   if (self->reference) {
1145     PyObject_GC_UnTrack(self);
1146     pyrna_struct_clear(self);
1147   }
1148 #endif /* !USE_PYRNA_STRUCT_REFERENCE */
1149
1150   /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */
1151   Py_TYPE(self)->tp_free(self);
1152 }
1153
1154 #ifdef USE_PYRNA_STRUCT_REFERENCE
1155 static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference)
1156 {
1157   if (self->reference) {
1158     //      PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */
1159     pyrna_struct_clear(self);
1160   }
1161   /* Reference is now NULL. */
1162
1163   if (reference) {
1164     self->reference = reference;
1165     Py_INCREF(reference);
1166     //      PyObject_GC_Track(self);  /* INITIALIZED TRACKED ? */
1167   }
1168 }
1169 #endif /* !USE_PYRNA_STRUCT_REFERENCE */
1170
1171 /* Use our own dealloc so we can free a property if we use one. */
1172 static void pyrna_prop_dealloc(BPy_PropertyRNA *self)
1173 {
1174 #ifdef USE_WEAKREFS
1175   if (self->in_weakreflist != NULL) {
1176     PyObject_ClearWeakRefs((PyObject *)self);
1177   }
1178 #endif
1179   /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */
1180   Py_TYPE(self)->tp_free(self);
1181 }
1182
1183 static void pyrna_prop_array_dealloc(BPy_PropertyRNA *self)
1184 {
1185 #ifdef USE_WEAKREFS
1186   if (self->in_weakreflist != NULL) {
1187     PyObject_ClearWeakRefs((PyObject *)self);
1188   }
1189 #endif
1190   /* Note, for subclassed PyObjects calling PyObject_DEL() directly crashes. */
1191   Py_TYPE(self)->tp_free(self);
1192 }
1193
1194 static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
1195 {
1196   const EnumPropertyItem *item;
1197   const char *result;
1198   bool free = false;
1199
1200   RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free);
1201   if (item) {
1202     result = BPy_enum_as_string(item);
1203   }
1204   else {
1205     result = "";
1206   }
1207
1208   if (free) {
1209     MEM_freeN((void *)item);
1210   }
1211
1212   return result;
1213 }
1214
1215 static int pyrna_string_to_enum(
1216     PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, const char *error_prefix)
1217 {
1218   const char *param = _PyUnicode_AsString(item);
1219
1220   if (param == NULL) {
1221     PyErr_Format(PyExc_TypeError,
1222                  "%.200s expected a string enum, not %.200s",
1223                  error_prefix,
1224                  Py_TYPE(item)->tp_name);
1225     return -1;
1226   }
1227   else {
1228     if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, r_value)) {
1229       const char *enum_str = pyrna_enum_as_string(ptr, prop);
1230       PyErr_Format(PyExc_TypeError,
1231                    "%.200s enum \"%.200s\" not found in (%s)",
1232                    error_prefix,
1233                    param,
1234                    enum_str);
1235       MEM_freeN((void *)enum_str);
1236       return -1;
1237     }
1238   }
1239
1240   return 0;
1241 }
1242
1243 /**
1244  * Takes a set of strings and map it to and array of booleans.
1245  *
1246  * Useful when the values aren't flags.
1247  *
1248  * \param type_convert_sign: Maps signed to unsigned range,
1249  * needed when we want to use the full range of a signed short/char.
1250  */
1251 BLI_bitmap *pyrna_set_to_enum_bitmap(const EnumPropertyItem *items,
1252                                      PyObject *value,
1253                                      int type_size,
1254                                      bool type_convert_sign,
1255                                      int bitmap_size,
1256                                      const char *error_prefix)
1257 {
1258   /* Set looping. */
1259   Py_ssize_t pos = 0;
1260   Py_ssize_t hash = 0;
1261   PyObject *key;
1262
1263   BLI_bitmap *bitmap = BLI_BITMAP_NEW(bitmap_size, __func__);
1264
1265   while (_PySet_NextEntry(value, &pos, &key, &hash)) {
1266     const char *param = _PyUnicode_AsString(key);
1267     if (param == NULL) {
1268       PyErr_Format(PyExc_TypeError,
1269                    "%.200s expected a string, not %.200s",
1270                    error_prefix,
1271                    Py_TYPE(key)->tp_name);
1272       goto error;
1273     }
1274
1275     int ret;
1276     if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) {
1277       goto error;
1278     }
1279
1280     int index = ret;
1281
1282     if (type_convert_sign) {
1283       if (type_size == 2) {
1284         union {
1285           signed short as_signed;
1286           unsigned short as_unsigned;
1287         } ret_convert;
1288         ret_convert.as_signed = (signed short)ret;
1289         index = (int)ret_convert.as_unsigned;
1290       }
1291       else if (type_size == 1) {
1292         union {
1293           signed char as_signed;
1294           unsigned char as_unsigned;
1295         } ret_convert;
1296         ret_convert.as_signed = (signed char)ret;
1297         index = (int)ret_convert.as_unsigned;
1298       }
1299       else {
1300         BLI_assert(0);
1301       }
1302     }
1303     BLI_assert(index < bitmap_size);
1304     BLI_BITMAP_ENABLE(bitmap, index);
1305   }
1306
1307   return bitmap;
1308
1309 error:
1310   MEM_freeN(bitmap);
1311   return NULL;
1312 }
1313
1314 /* 'value' _must_ be a set type, error check before calling. */
1315 int pyrna_set_to_enum_bitfield(const EnumPropertyItem *items,
1316                                PyObject *value,
1317                                int *r_value,
1318                                const char *error_prefix)
1319 {
1320   /* Set of enum items, concatenate all values with OR. */
1321   int ret, flag = 0;
1322
1323   /* Set looping. */
1324   Py_ssize_t pos = 0;
1325   Py_ssize_t hash = 0;
1326   PyObject *key;
1327
1328   *r_value = 0;
1329
1330   while (_PySet_NextEntry(value, &pos, &key, &hash)) {
1331     const char *param = _PyUnicode_AsString(key);
1332
1333     if (param == NULL) {
1334       PyErr_Format(PyExc_TypeError,
1335                    "%.200s expected a string, not %.200s",
1336                    error_prefix,
1337                    Py_TYPE(key)->tp_name);
1338       return -1;
1339     }
1340
1341     if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) {
1342       return -1;
1343     }
1344
1345     flag |= ret;
1346   }
1347
1348   *r_value = flag;
1349   return 0;
1350 }
1351
1352 static int pyrna_prop_to_enum_bitfield(
1353     PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, const char *error_prefix)
1354 {
1355   const EnumPropertyItem *item;
1356   int ret;
1357   bool free = false;
1358
1359   *r_value = 0;
1360
1361   if (!PyAnySet_Check(value)) {
1362     PyErr_Format(PyExc_TypeError,
1363                  "%.200s, %.200s.%.200s expected a set, not a %.200s",
1364                  error_prefix,
1365                  RNA_struct_identifier(ptr->type),
1366                  RNA_property_identifier(prop),
1367                  Py_TYPE(value)->tp_name);
1368     return -1;
1369   }
1370
1371   RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free);
1372
1373   if (item) {
1374     ret = pyrna_set_to_enum_bitfield(item, value, r_value, error_prefix);
1375   }
1376   else {
1377     if (PySet_GET_SIZE(value)) {
1378       PyErr_Format(PyExc_TypeError,
1379                    "%.200s: empty enum \"%.200s\" could not have any values assigned",
1380                    error_prefix,
1381                    RNA_property_identifier(prop));
1382       ret = -1;
1383     }
1384     else {
1385       ret = 0;
1386     }
1387   }
1388
1389   if (free) {
1390     MEM_freeN((void *)item);
1391   }
1392
1393   return ret;
1394 }
1395
1396 PyObject *pyrna_enum_bitfield_to_py(const EnumPropertyItem *items, int value)
1397 {
1398   PyObject *ret = PySet_New(NULL);
1399   const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1];
1400
1401   if (RNA_enum_bitflag_identifiers(items, value, identifier)) {
1402     PyObject *item;
1403     int index;
1404     for (index = 0; identifier[index]; index++) {
1405       item = PyUnicode_FromString(identifier[index]);
1406       PySet_Add(ret, item);
1407       Py_DECREF(item);
1408     }
1409   }
1410
1411   return ret;
1412 }
1413
1414 static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
1415 {
1416   PyObject *item, *ret = NULL;
1417
1418   if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
1419     const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1];
1420
1421     ret = PySet_New(NULL);
1422
1423     if (RNA_property_enum_bitflag_identifiers(BPy_GetContext(), ptr, prop, val, identifier)) {
1424       int index;
1425
1426       for (index = 0; identifier[index]; index++) {
1427         item = PyUnicode_FromString(identifier[index]);
1428         PySet_Add(ret, item);
1429         Py_DECREF(item);
1430       }
1431     }
1432   }
1433   else {
1434     const char *identifier;
1435     if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) {
1436       ret = PyUnicode_FromString(identifier);
1437     }
1438     else {
1439       /* Static, no need to free. */
1440       const EnumPropertyItem *enum_item;
1441       bool free_dummy;
1442       RNA_property_enum_items_ex(NULL, ptr, prop, true, &enum_item, NULL, &free_dummy);
1443       BLI_assert(!free_dummy);
1444
1445       /* Do not print warning in case of DummyRNA_NULL_items,
1446        * this one will never match any value... */
1447       if (enum_item != DummyRNA_NULL_items) {
1448         const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL);
1449
1450         /* Prefer not to fail silently in case of API errors, maybe disable it later. */
1451         CLOG_WARN(BPY_LOG_RNA,
1452                   "current value '%d' "
1453                   "matches no enum in '%s', '%s', '%s'",
1454                   val,
1455                   RNA_struct_identifier(ptr->type),
1456                   ptr_name,
1457                   RNA_property_identifier(prop));
1458
1459 #if 0 /* Gives Python decoding errors while generating docs :( */
1460         char error_str[256];
1461         BLI_snprintf(error_str,
1462                      sizeof(error_str),
1463                      "RNA Warning: Current value \"%d\" "
1464                      "matches no enum in '%s', '%s', '%s'",
1465                      val,
1466                      RNA_struct_identifier(ptr->type),
1467                      ptr_name,
1468                      RNA_property_identifier(prop));
1469
1470         PyErr_Warn(PyExc_RuntimeWarning, error_str);
1471 #endif
1472
1473         if (ptr_name) {
1474           MEM_freeN((void *)ptr_name);
1475         }
1476       }
1477
1478       ret = PyUnicode_FromString("");
1479 #if 0
1480       PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val);
1481       ret = NULL;
1482 #endif
1483     }
1484   }
1485
1486   return ret;
1487 }
1488
1489 PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
1490 {
1491   PyObject *ret;
1492   const int type = RNA_property_type(prop);
1493
1494   if (RNA_property_array_check(prop)) {
1495     return pyrna_py_from_array(ptr, prop);
1496   }
1497
1498   /* See if we can coerce into a Python type - 'PropertyType'. */
1499   switch (type) {
1500     case PROP_BOOLEAN:
1501       ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop));
1502       break;
1503     case PROP_INT:
1504       ret = PyLong_FromLong(RNA_property_int_get(ptr, prop));
1505       break;
1506     case PROP_FLOAT:
1507       ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop));
1508       break;
1509     case PROP_STRING: {
1510       const int subtype = RNA_property_subtype(prop);
1511       const char *buf;
1512       int buf_len;
1513       char buf_fixed[32];
1514
1515       buf = RNA_property_string_get_alloc(ptr, prop, buf_fixed, sizeof(buf_fixed), &buf_len);
1516 #ifdef USE_STRING_COERCE
1517       /* Only file paths get special treatment, they may contain non utf-8 chars. */
1518       if (subtype == PROP_BYTESTRING) {
1519         ret = PyBytes_FromStringAndSize(buf, buf_len);
1520       }
1521       else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
1522         ret = PyC_UnicodeFromByteAndSize(buf, buf_len);
1523       }
1524       else {
1525         ret = PyUnicode_FromStringAndSize(buf, buf_len);
1526       }
1527 #else  /* USE_STRING_COERCE */
1528       if (subtype == PROP_BYTESTRING) {
1529         ret = PyBytes_FromStringAndSize(buf, buf_len);
1530       }
1531       else {
1532         ret = PyUnicode_FromStringAndSize(buf, buf_len);
1533       }
1534 #endif /* USE_STRING_COERCE */
1535       if (buf_fixed != buf) {
1536         MEM_freeN((void *)buf);
1537       }
1538       break;
1539     }
1540     case PROP_ENUM: {
1541       ret = pyrna_enum_to_py(ptr, prop, RNA_property_enum_get(ptr, prop));
1542       break;
1543     }
1544     case PROP_POINTER: {
1545       PointerRNA newptr;
1546       newptr = RNA_property_pointer_get(ptr, prop);
1547       if (newptr.data) {
1548         ret = pyrna_struct_CreatePyObject(&newptr);
1549       }
1550       else {
1551         ret = Py_None;
1552         Py_INCREF(ret);
1553       }
1554       break;
1555     }
1556     case PROP_COLLECTION:
1557       ret = pyrna_prop_CreatePyObject(ptr, prop);
1558       break;
1559     default:
1560       PyErr_Format(PyExc_TypeError,
1561                    "bpy_struct internal error: unknown type '%d' (pyrna_prop_to_py)",
1562                    type);
1563       ret = NULL;
1564       break;
1565   }
1566
1567   return ret;
1568 }
1569
1570 /**
1571  * This function is used by operators and converting dicts into collections.
1572  * It takes keyword args and fills them with property values.
1573  */
1574 int pyrna_pydict_to_props(PointerRNA *ptr,
1575                           PyObject *kw,
1576                           const bool all_args,
1577                           const char *error_prefix)
1578 {
1579   int error_val = 0;
1580   int totkw;
1581   const char *arg_name = NULL;
1582   PyObject *item;
1583
1584   totkw = kw ? PyDict_Size(kw) : 0;
1585
1586   RNA_STRUCT_BEGIN (ptr, prop) {
1587     arg_name = RNA_property_identifier(prop);
1588
1589     if (STREQ(arg_name, "rna_type")) {
1590       continue;
1591     }
1592
1593     if (kw == NULL) {
1594       PyErr_Format(PyExc_TypeError,
1595                    "%.200s: no keywords, expected \"%.200s\"",
1596                    error_prefix,
1597                    arg_name ? arg_name : "<UNKNOWN>");
1598       error_val = -1;
1599       break;
1600     }
1601
1602     item = PyDict_GetItemString(kw, arg_name); /* Wont set an error. */
1603
1604     if (item == NULL) {
1605       if (all_args) {
1606         PyErr_Format(PyExc_TypeError,
1607                      "%.200s: keyword \"%.200s\" missing",
1608                      error_prefix,
1609                      arg_name ? arg_name : "<UNKNOWN>");
1610         error_val = -1; /* pyrna_py_to_prop sets the error. */
1611         break;
1612       }
1613     }
1614     else {
1615       if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) {
1616         error_val = -1;
1617         break;
1618       }
1619       totkw--;
1620     }
1621   }
1622   RNA_STRUCT_END;
1623
1624   if (error_val == 0 && totkw > 0) { /* Some keywords were given that were not used :/. */
1625     PyObject *key, *value;
1626     Py_ssize_t pos = 0;
1627
1628     while (PyDict_Next(kw, &pos, &key, &value)) {
1629       arg_name = _PyUnicode_AsString(key);
1630       if (RNA_struct_find_property(ptr, arg_name) == NULL) {
1631         break;
1632       }
1633       arg_name = NULL;
1634     }
1635
1636     PyErr_Format(PyExc_TypeError,
1637                  "%.200s: keyword \"%.200s\" unrecognized",
1638                  error_prefix,
1639                  arg_name ? arg_name : "<UNKNOWN>");
1640     error_val = -1;
1641   }
1642
1643   return error_val;
1644 }
1645
1646 static PyObject *pyrna_func_to_py(const PointerRNA *ptr, FunctionRNA *func)
1647 {
1648   BPy_FunctionRNA *pyfunc = (BPy_FunctionRNA *)PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type);
1649   pyfunc->ptr = *ptr;
1650   pyfunc->func = func;
1651   return (PyObject *)pyfunc;
1652 }
1653
1654 static int pyrna_py_to_prop(
1655     PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix)
1656 {
1657   /* XXX hard limits should be checked here. */
1658   const int type = RNA_property_type(prop);
1659
1660   if (RNA_property_array_check(prop)) {
1661     /* Done getting the length. */
1662     if (pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) {
1663       return -1;
1664     }
1665   }
1666   else {
1667     /* Normal Property (not an array). */
1668
1669     /* See if we can coerce into a Python type - 'PropertyType'. */
1670     switch (type) {
1671       case PROP_BOOLEAN: {
1672         int param;
1673         /* Prefer not to have an exception here
1674          * however so many poll functions return None or a valid Object.
1675          * It's a hassle to convert these into a bool before returning. */
1676         if (RNA_parameter_flag(prop) & PARM_OUTPUT) {
1677           param = PyObject_IsTrue(value);
1678         }
1679         else {
1680           param = PyC_Long_AsI32(value);
1681
1682           if (UNLIKELY(param & ~1)) { /* Only accept 0/1. */
1683             param = -1;               /* Error out below. */
1684           }
1685         }
1686
1687         if (param == -1) {
1688           PyErr_Format(PyExc_TypeError,
1689                        "%.200s %.200s.%.200s expected True/False or 0/1, not %.200s",
1690                        error_prefix,
1691                        RNA_struct_identifier(ptr->type),
1692                        RNA_property_identifier(prop),
1693                        Py_TYPE(value)->tp_name);
1694           return -1;
1695         }
1696         else {
1697           if (data) {
1698             *((bool *)data) = param;
1699           }
1700           else {
1701             RNA_property_boolean_set(ptr, prop, param);
1702           }
1703         }
1704         break;
1705       }
1706       case PROP_INT: {
1707         int overflow;
1708         long param = PyLong_AsLongAndOverflow(value, &overflow);
1709         if (overflow || (param > INT_MAX) || (param < INT_MIN)) {
1710           PyErr_Format(PyExc_ValueError,
1711                        "%.200s %.200s.%.200s value not in 'int' range "
1712                        "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")",
1713                        error_prefix,
1714                        RNA_struct_identifier(ptr->type),
1715                        RNA_property_identifier(prop));
1716           return -1;
1717         }
1718         else if (param == -1 && PyErr_Occurred()) {
1719           PyErr_Format(PyExc_TypeError,
1720                        "%.200s %.200s.%.200s expected an int type, not %.200s",
1721                        error_prefix,
1722                        RNA_struct_identifier(ptr->type),
1723                        RNA_property_identifier(prop),
1724                        Py_TYPE(value)->tp_name);
1725           return -1;
1726         }
1727         else {
1728           int param_i = (int)param;
1729           if (data) {
1730             RNA_property_int_clamp(ptr, prop, &param_i);
1731             *((int *)data) = param_i;
1732           }
1733           else {
1734             RNA_property_int_set(ptr, prop, param_i);
1735           }
1736         }
1737         break;
1738       }
1739       case PROP_FLOAT: {
1740         float param = PyFloat_AsDouble(value);
1741         if (PyErr_Occurred()) {
1742           PyErr_Format(PyExc_TypeError,
1743                        "%.200s %.200s.%.200s expected a float type, not %.200s",
1744                        error_prefix,
1745                        RNA_struct_identifier(ptr->type),
1746                        RNA_property_identifier(prop),
1747                        Py_TYPE(value)->tp_name);
1748           return -1;
1749         }
1750         else {
1751           if (data) {
1752             RNA_property_float_clamp(ptr, prop, (float *)&param);
1753             *((float *)data) = param;
1754           }
1755           else {
1756             RNA_property_float_set(ptr, prop, param);
1757           }
1758         }
1759         break;
1760       }
1761       case PROP_STRING: {
1762         const int subtype = RNA_property_subtype(prop);
1763         const char *param;
1764
1765         if (value == Py_None) {
1766           if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) {
1767             if (data) {
1768               *((char **)data) = (char *)NULL;
1769             }
1770             else {
1771               RNA_property_string_set(ptr, prop, NULL);
1772             }
1773           }
1774           else {
1775             PyC_Err_Format_Prefix(PyExc_TypeError,
1776                                   "%.200s %.200s.%.200s doesn't support None from string types",
1777                                   error_prefix,
1778                                   RNA_struct_identifier(ptr->type),
1779                                   RNA_property_identifier(prop));
1780             return -1;
1781           }
1782         }
1783         else if (subtype == PROP_BYTESTRING) {
1784
1785           /* Byte String. */
1786
1787           param = PyBytes_AsString(value);
1788
1789           if (param == NULL) {
1790             if (PyBytes_Check(value)) {
1791               /* there was an error assigning a string type,
1792                * rather than setting a new error, prefix the existing one
1793                */
1794               PyC_Err_Format_Prefix(PyExc_TypeError,
1795                                     "%.200s %.200s.%.200s error assigning bytes",
1796                                     error_prefix,
1797                                     RNA_struct_identifier(ptr->type),
1798                                     RNA_property_identifier(prop));
1799             }
1800             else {
1801               PyErr_Format(PyExc_TypeError,
1802                            "%.200s %.200s.%.200s expected a bytes type, not %.200s",
1803                            error_prefix,
1804                            RNA_struct_identifier(ptr->type),
1805                            RNA_property_identifier(prop),
1806                            Py_TYPE(value)->tp_name);
1807             }
1808
1809             return -1;
1810           }
1811           else {
1812             if (data) {
1813               *((char **)data) = (char *)param;
1814             }
1815             else {
1816               RNA_property_string_set_bytes(ptr, prop, param, PyBytes_Size(value));
1817             }
1818           }
1819         }
1820         else {
1821           /* Unicode String. */
1822 #ifdef USE_STRING_COERCE
1823           PyObject *value_coerce = NULL;
1824           if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
1825             /* TODO, get size. */
1826             param = PyC_UnicodeAsByte(value, &value_coerce);
1827           }
1828           else {
1829             param = _PyUnicode_AsString(value);
1830           }
1831 #else  /* USE_STRING_COERCE */
1832           param = _PyUnicode_AsString(value);
1833 #endif /* USE_STRING_COERCE */
1834
1835           if (param == NULL) {
1836             if (PyUnicode_Check(value)) {
1837               /* there was an error assigning a string type,
1838                * rather than setting a new error, prefix the existing one
1839                */
1840               PyC_Err_Format_Prefix(PyExc_TypeError,
1841                                     "%.200s %.200s.%.200s error assigning string",
1842                                     error_prefix,
1843                                     RNA_struct_identifier(ptr->type),
1844                                     RNA_property_identifier(prop));
1845             }
1846             else {
1847               PyErr_Format(PyExc_TypeError,
1848                            "%.200s %.200s.%.200s expected a string type, not %.200s",
1849                            error_prefix,
1850                            RNA_struct_identifier(ptr->type),
1851                            RNA_property_identifier(prop),
1852                            Py_TYPE(value)->tp_name);
1853             }
1854
1855             return -1;
1856           }
1857           else {
1858             /* Same as bytes. */
1859             /* XXX, this is suspect, but needed for function calls,
1860              * need to see if there's a better way. */
1861             if (data) {
1862               *((char **)data) = (char *)param;
1863             }
1864             else {
1865               RNA_property_string_set(ptr, prop, param);
1866             }
1867           }
1868 #ifdef USE_STRING_COERCE
1869           Py_XDECREF(value_coerce);
1870 #endif /* USE_STRING_COERCE */
1871         }
1872         break;
1873       }
1874       case PROP_ENUM: {
1875         int val = 0;
1876
1877         /* Type checking is done by each function. */
1878         if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
1879           /* Set of enum items, concatenate all values with OR. */
1880           if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) == -1) {
1881             return -1;
1882           }
1883         }
1884         else {
1885           /* Simple enum string. */
1886           if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) == -1) {
1887             return -1;
1888           }
1889         }
1890
1891         if (data) {
1892           *((int *)data) = val;
1893         }
1894         else {
1895           RNA_property_enum_set(ptr, prop, val);
1896         }
1897
1898         break;
1899       }
1900       case PROP_POINTER: {
1901         PyObject *value_new = NULL;
1902
1903         StructRNA *ptr_type = RNA_property_pointer_type(ptr, prop);
1904         int flag = RNA_property_flag(prop);
1905         int flag_parameter = RNA_parameter_flag(prop);
1906
1907         /* This is really nasty! Done so we can fake the operator having direct properties, eg:
1908          * layout.prop(self, "filepath")
1909          * ... which in fact should be:
1910          * layout.prop(self.properties, "filepath")
1911          *
1912          * we need to do this trick.
1913          * if the prop is not an operator type and the pyobject is an operator,
1914          * use its properties in place of itself.
1915          *
1916          * This is so bad that it is almost a good reason to do away with fake
1917          * 'self.properties -> self'
1918          * class mixing. If this causes problems in the future it should be removed.
1919          */
1920         if ((ptr_type == &RNA_AnyType) && (BPy_StructRNA_Check(value))) {
1921           const StructRNA *base_type = RNA_struct_base_child_of(
1922               ((const BPy_StructRNA *)value)->ptr.type, NULL);
1923           if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) {
1924             value = PyObject_GetAttr(value, bpy_intern_str_properties);
1925             value_new = value;
1926           }
1927         }
1928
1929         /* if property is an OperatorProperties/GizmoProperties pointer and value is a map,
1930          * forward back to pyrna_pydict_to_props */
1931         if (PyDict_Check(value)) {
1932           const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL);
1933           if (base_type == &RNA_OperatorProperties) {
1934             PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
1935             return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
1936           }
1937           else if (base_type == &RNA_GizmoProperties) {
1938             PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
1939             return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
1940           }
1941         }
1942
1943         /* Another exception, allow to pass a collection as an RNA property. */
1944         if (Py_TYPE(value) == &pyrna_prop_collection_Type) { /* Ok to ignore idprop collections. */
1945           PointerRNA c_ptr;
1946           BPy_PropertyRNA *value_prop = (BPy_PropertyRNA *)value;
1947           if (RNA_property_collection_type_get(&value_prop->ptr, value_prop->prop, &c_ptr)) {
1948             value = pyrna_struct_CreatePyObject(&c_ptr);
1949             value_new = value;
1950           }
1951           else {
1952             PyErr_Format(PyExc_TypeError,
1953                          "%.200s %.200s.%.200s collection has no type, "
1954                          "can't be used as a %.200s type",
1955                          error_prefix,
1956                          RNA_struct_identifier(ptr->type),
1957                          RNA_property_identifier(prop),
1958                          RNA_struct_identifier(ptr_type));
1959             return -1;
1960           }
1961         }
1962
1963         if (!BPy_StructRNA_Check(value) && value != Py_None) {
1964           PyErr_Format(PyExc_TypeError,
1965                        "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
1966                        error_prefix,
1967                        RNA_struct_identifier(ptr->type),
1968                        RNA_property_identifier(prop),
1969                        RNA_struct_identifier(ptr_type),
1970                        Py_TYPE(value)->tp_name);
1971           Py_XDECREF(value_new);
1972           return -1;
1973         }
1974         else if ((flag & PROP_NEVER_NULL) && value == Py_None) {
1975           PyErr_Format(PyExc_TypeError,
1976                        "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type",
1977                        error_prefix,
1978                        RNA_struct_identifier(ptr->type),
1979                        RNA_property_identifier(prop),
1980                        RNA_struct_identifier(ptr_type));
1981           Py_XDECREF(value_new);
1982           return -1;
1983         }
1984         else if ((value != Py_None) && ((flag & PROP_ID_SELF_CHECK) &&
1985                                         ptr->id.data == ((BPy_StructRNA *)value)->ptr.id.data)) {
1986           PyErr_Format(PyExc_TypeError,
1987                        "%.200s %.200s.%.200s ID type does not support assignment to itself",
1988                        error_prefix,
1989                        RNA_struct_identifier(ptr->type),
1990                        RNA_property_identifier(prop));
1991           Py_XDECREF(value_new);
1992           return -1;
1993         }
1994         else {
1995           BPy_StructRNA *param = (BPy_StructRNA *)value;
1996           bool raise_error = false;
1997           if (data) {
1998
1999             if (flag_parameter & PARM_RNAPTR) {
2000               if (flag & PROP_THICK_WRAP) {
2001                 if (value == Py_None) {
2002                   memset(data, 0, sizeof(PointerRNA));
2003                 }
2004                 else if (RNA_struct_is_a(param->ptr.type, ptr_type)) {
2005                   *((PointerRNA *)data) = param->ptr;
2006                 }
2007                 else {
2008                   raise_error = true;
2009                 }
2010               }
2011               else {
2012                 /* For function calls, we sometimes want to pass the 'ptr' directly,
2013                  * but watch out that it remains valid!
2014                  * We could possibly support this later if needed. */
2015                 BLI_assert(value_new == NULL);
2016                 if (value == Py_None) {
2017                   *((void **)data) = NULL;
2018                 }
2019                 else if (RNA_struct_is_a(param->ptr.type, ptr_type)) {
2020                   *((PointerRNA **)data) = &param->ptr;
2021                 }
2022                 else {
2023                   raise_error = true;
2024                 }
2025               }
2026             }
2027             else if (value == Py_None) {
2028               *((void **)data) = NULL;
2029             }
2030             else if (RNA_struct_is_a(param->ptr.type, ptr_type)) {
2031               *((void **)data) = param->ptr.data;
2032             }
2033             else {
2034               raise_error = true;
2035             }
2036           }
2037           else {
2038             /* Data == NULL, assign to RNA. */
2039             if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) {
2040               ReportList reports;
2041               BKE_reports_init(&reports, RPT_STORE);
2042               RNA_property_pointer_set(
2043                   ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr, &reports);
2044               int err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true));
2045               if (err == -1) {
2046                 Py_XDECREF(value_new);
2047                 return -1;
2048               }
2049             }
2050             else {
2051               raise_error = true;
2052             }
2053           }
2054
2055           if (raise_error) {
2056             if (pyrna_struct_validity_check(param) == -1) {
2057               /* Error set. */
2058             }
2059             else {
2060               PointerRNA tmp;
2061               RNA_pointer_create(NULL, ptr_type, NULL, &tmp);
2062               PyErr_Format(PyExc_TypeError,
2063                            "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
2064                            error_prefix,
2065                            RNA_struct_identifier(ptr->type),
2066                            RNA_property_identifier(prop),
2067                            RNA_struct_identifier(tmp.type),
2068                            RNA_struct_identifier(param->ptr.type));
2069             }
2070             Py_XDECREF(value_new);
2071             return -1;
2072           }
2073         }
2074
2075         Py_XDECREF(value_new);
2076
2077         break;
2078       }
2079       case PROP_COLLECTION: {
2080         Py_ssize_t seq_len, i;
2081         PyObject *item;
2082         PointerRNA itemptr;
2083         ListBase *lb;
2084         CollectionPointerLink *link;
2085
2086         lb = (data) ? (ListBase *)data : NULL;
2087
2088         /* Convert a sequence of dict's into a collection. */
2089         if (!PySequence_Check(value)) {
2090           PyErr_Format(
2091               PyExc_TypeError,
2092               "%.200s %.200s.%.200s expected a sequence for an RNA collection, not %.200s",
2093               error_prefix,
2094               RNA_struct_identifier(ptr->type),
2095               RNA_property_identifier(prop),
2096               Py_TYPE(value)->tp_name);
2097           return -1;
2098         }
2099
2100         seq_len = PySequence_Size(value);
2101         for (i = 0; i < seq_len; i++) {
2102           item = PySequence_GetItem(value, i);
2103
2104           if (item == NULL) {
2105             PyErr_Format(
2106                 PyExc_TypeError,
2107                 "%.200s %.200s.%.200s failed to get sequence index '%d' for an RNA collection",
2108                 error_prefix,
2109                 RNA_struct_identifier(ptr->type),
2110                 RNA_property_identifier(prop),
2111                 i);
2112             Py_XDECREF(item);
2113             return -1;
2114           }
2115
2116           if (PyDict_Check(item) == 0) {
2117             PyErr_Format(PyExc_TypeError,
2118                          "%.200s %.200s.%.200s expected a each sequence "
2119                          "member to be a dict for an RNA collection, not %.200s",
2120                          error_prefix,
2121                          RNA_struct_identifier(ptr->type),
2122                          RNA_property_identifier(prop),
2123                          Py_TYPE(item)->tp_name);
2124             Py_XDECREF(item);
2125             return -1;
2126           }
2127
2128           if (lb) {
2129             link = MEM_callocN(sizeof(CollectionPointerLink), "PyCollectionPointerLink");
2130             link->ptr = itemptr;
2131             BLI_addtail(lb, link);
2132           }
2133           else {
2134             RNA_property_collection_add(ptr, prop, &itemptr);
2135           }
2136
2137           if (pyrna_pydict_to_props(
2138                   &itemptr, item, true, "Converting a Python list to an RNA collection") == -1) {
2139             PyObject *msg = PyC_ExceptionBuffer();
2140             const char *msg_char = _PyUnicode_AsString(msg);
2141
2142             PyErr_Format(PyExc_TypeError,
2143                          "%.200s %.200s.%.200s error converting a member of a collection "
2144                          "from a dicts into an RNA collection, failed with: %s",
2145                          error_prefix,
2146                          RNA_struct_identifier(ptr->type),
2147                          RNA_property_identifier(prop),
2148                          msg_char);
2149
2150             Py_DECREF(item);
2151             Py_DECREF(msg);
2152             return -1;
2153           }
2154           Py_DECREF(item);
2155         }
2156
2157         break;
2158       }
2159       default:
2160         PyErr_Format(PyExc_AttributeError,
2161                      "%.200s %.200s.%.200s unknown property type (pyrna_py_to_prop)",
2162                      error_prefix,
2163                      RNA_struct_identifier(ptr->type),
2164                      RNA_property_identifier(prop));
2165         return -1;
2166     }
2167   }
2168
2169   /* Run RNA property functions. */
2170   if (RNA_property_update_check(prop)) {
2171     RNA_property_update(BPy_GetContext(), ptr, prop);
2172   }
2173
2174   return 0;
2175 }
2176
2177 static PyObject *pyrna_prop_array_to_py_index(BPy_PropertyArrayRNA *self, int index)
2178 {
2179   PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
2180   return pyrna_py_from_array_index(self, &self->ptr, self->prop, index);
2181 }
2182
2183 static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, PyObject *value)
2184 {
2185   int ret = 0;
2186   PointerRNA *ptr = &self->ptr;
2187   PropertyRNA *prop = self->prop;
2188
2189   const int totdim = RNA_property_array_dimension(ptr, prop, NULL);
2190
2191   if (totdim > 1) {
2192     // char error_str[512];
2193     if (pyrna_py_to_array_index(
2194             &self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "") == -1) {
2195       /* Error is set. */
2196       ret = -1;
2197     }
2198   }
2199   else {
2200     /* See if we can coerce into a Python type - 'PropertyType'. */
2201     switch (RNA_property_type(prop)) {
2202       case PROP_BOOLEAN: {
2203         int param = PyC_Long_AsBool(value);
2204
2205         if (param == -1) {
2206           /* Error is set. */
2207           ret = -1;
2208         }
2209         else {
2210           RNA_property_boolean_set_index(ptr, prop, index, param);
2211         }
2212         break;
2213       }
2214       case PROP_INT: {
2215         int param = PyC_Long_AsI32(value);
2216         if (param == -1 && PyErr_Occurred()) {
2217           PyErr_SetString(PyExc_TypeError, "expected an int type");
2218           ret = -1;
2219         }
2220         else {
2221           RNA_property_int_clamp(ptr, prop, &param);
2222           RNA_property_int_set_index(ptr, prop, index, param);
2223         }
2224         break;
2225       }
2226       case PROP_FLOAT: {
2227         float param = PyFloat_AsDouble(value);
2228         if (PyErr_Occurred()) {
2229           PyErr_SetString(PyExc_TypeError, "expected a float type");
2230           ret = -1;
2231         }
2232         else {
2233           RNA_property_float_clamp(ptr, prop, &param);
2234           RNA_property_float_set_index(ptr, prop, index, param);
2235         }
2236         break;
2237       }
2238       default:
2239         PyErr_SetString(PyExc_AttributeError, "not an array type");
2240         ret = -1;
2241         break;
2242     }
2243   }
2244
2245   /* Run RNA property functions. */
2246   if (RNA_property_update_check(prop)) {
2247     RNA_property_update(BPy_GetContext(), ptr, prop);
2248   }
2249
2250   return ret;
2251 }
2252
2253 /* ---------------sequence------------------------------------------- */
2254 static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self)
2255 {
2256   PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self);
2257
2258   if (RNA_property_array_dimension(&self->ptr, self->prop, NULL) > 1) {
2259     return RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim);
2260   }
2261   else {
2262     return RNA_property_array_length(&self->ptr, self->prop);
2263   }
2264 }
2265
2266 static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self)
2267 {
2268   PYRNA_PROP_CHECK_INT(self);
2269
2270   return RNA_property_collection_length(&self->ptr, self->prop);
2271 }
2272
2273 /* bool functions are for speed, so we can avoid getting the length
2274  * of 1000's of items in a linked list for eg. */
2275 static int pyrna_prop_array_bool(BPy_PropertyRNA *self)
2276 {
2277   PYRNA_PROP_CHECK_INT(self);
2278
2279   return RNA_property_array_length(&self->ptr, self->prop) ? 1 : 0;
2280 }
2281
2282 static int pyrna_prop_collection_bool(BPy_PropertyRNA *self)
2283 {
2284   /* No callback defined, just iterate and find the nth item. */
2285   CollectionPropertyIterator iter;
2286   int test;
2287
2288   PYRNA_PROP_CHECK_INT(self);
2289
2290   RNA_property_collection_begin(&self->ptr, self->prop, &iter);
2291   test = iter.valid;
2292   RNA_property_collection_end(&iter);
2293   return test;
2294 }
2295
2296 /* notice getting the length of the collection is avoided unless negative
2297  * index is used or to detect internal error with a valid index.
2298  * This is done for faster lookups. */
2299 #define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \
2300   if (keynum < 0) { \
2301     keynum_abs += RNA_property_collection_length(&self->ptr, self->prop); \
2302     if (keynum_abs < 0) { \
2303       PyErr_Format(PyExc_IndexError, "bpy_prop_collection[%d]: out of range.", keynum); \
2304       return ret_err; \
2305     } \
2306   } \
2307   (void)0
2308
2309 /* Internal use only. */
2310 static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum)
2311 {
2312   PointerRNA newptr;
2313   Py_ssize_t keynum_abs = keynum;
2314
2315   PYRNA_PROP_CHECK_OBJ(self);
2316
2317   PYRNA_PROP_COLLECTION_ABS_INDEX(NULL);
2318
2319   if (RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) {
2320     return pyrna_struct_CreatePyObject(&newptr);
2321   }
2322   else {
2323     const int len = RNA_property_collection_length(&self->ptr, self->prop);
2324     if (keynum_abs >= len) {
2325       PyErr_Format(PyExc_IndexError,
2326                    "bpy_prop_collection[index]: "
2327                    "index %d out of range, size %d",
2328                    keynum,
2329                    len);
2330     }
2331     else {
2332       PyErr_Format(PyExc_RuntimeError,
2333                    "bpy_prop_collection[index]: internal error, "
2334                    "valid index %d given in %d sized collection, but value not found",
2335                    keynum_abs,
2336                    len);
2337     }
2338
2339     return NULL;
2340   }
2341 }
2342
2343 /* Values type must have been already checked. */
2344 static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self,
2345                                                    Py_ssize_t keynum,
2346                                                    PyObject *value)
2347 {
2348   Py_ssize_t keynum_abs = keynum;
2349   const PointerRNA *ptr = (value == Py_None) ? (&PointerRNA_NULL) : &((BPy_StructRNA *)value)->ptr;
2350
2351   PYRNA_PROP_CHECK_INT(self);
2352
2353   PYRNA_PROP_COLLECTION_ABS_INDEX(-1);
2354
2355   if (RNA_property_collection_assign_int(&self->ptr, self->prop, keynum_abs, ptr) == 0) {
2356     const int len = RNA_property_collection_length(&self->ptr, self->prop);
2357     if (keynum_abs >= len) {
2358       PyErr_Format(PyExc_IndexError,
2359                    "bpy_prop_collection[index] = value: "
2360                    "index %d out of range, size %d",
2361                    keynum,
2362                    len);
2363     }
2364     else {
2365
2366       PyErr_Format(PyExc_IndexError,
2367                    "bpy_prop_collection[index] = value: "
2368                    "failed assignment (unknown reason)",
2369                    keynum);
2370     }
2371     return -1;
2372   }
2373
2374   return 0;
2375 }
2376
2377 static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, int keynum)
2378 {
2379   int len;
2380
2381   PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
2382
2383   len = pyrna_prop_array_length(self);
2384
2385   if (keynum < 0) {
2386     keynum += len;
2387   }
2388
2389   if (keynum >= 0 && keynum < len) {
2390     return pyrna_prop_array_to_py_index(self, keynum);
2391   }
2392
2393   PyErr_Format(PyExc_IndexError, "bpy_prop_array[index]: index %d out of range", keynum);
2394   return NULL;
2395 }
2396
2397 static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, const char *keyname)
2398 {
2399   PointerRNA newptr;
2400
2401   PYRNA_PROP_CHECK_OBJ(self);
2402
2403   if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) {
2404     return pyrna_struct_CreatePyObject(&newptr);
2405   }
2406
2407   PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname);
2408   return NULL;
2409 }
2410 // static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname)
2411
2412 /**
2413  * Special case: `bpy.data.objects["some_id_name", "//some_lib_name.blend"]`
2414  * also for:     `bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback)`
2415  *
2416  * \note
2417  * error codes since this is not to be called directly from Python,
2418  * this matches Python's `__contains__` values C-API.
2419  * - -1: exception set
2420  * -  0: not found
2421  * -  1: found
2422  */
2423 static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self,
2424                                                             PyObject *key,
2425                                                             const char *err_prefix,
2426                                                             const short err_not_found,
2427                                                             PointerRNA *r_ptr)
2428 {
2429   const char *keyname;
2430
2431   /* First validate the args, all we know is that they are a tuple. */
2432   if (PyTuple_GET_SIZE(key) != 2) {
2433     PyErr_Format(PyExc_KeyError,
2434                  "%s: tuple key must be a pair, not size %d",
2435                  err_prefix,
2436                  PyTuple_GET_SIZE(key));
2437     return -1;
2438   }
2439   else if (self->ptr.type != &RNA_BlendData) {
2440     PyErr_Format(PyExc_KeyError,
2441                  "%s: is only valid for bpy.data collections, not %.200s",
2442                  err_prefix,
2443                  RNA_struct_identifier(self->ptr.type));
2444     return -1;
2445   }
2446   else if ((keyname = _PyUnicode_AsString(PyTuple_GET_ITEM(key, 0))) == NULL) {
2447     PyErr_Format(PyExc_KeyError,
2448                  "%s: id must be a string, not %.200s",
2449                  err_prefix,
2450                  Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name);
2451     return -1;
2452   }
2453   else {
2454     PyObject *keylib = PyTuple_GET_ITEM(key, 1);
2455     Library *lib;
2456     bool found = false;
2457
2458     if (keylib == Py_None) {
2459       lib = NULL;
2460     }
2461     else if (PyUnicode_Check(keylib)) {
2462       Main *bmain = self->ptr.data;
2463       const char *keylib_str = _PyUnicode_AsString(keylib);
2464       lib = BLI_findstring(&bmain->libraries, keylib_str, offsetof(Library, name));
2465       if (lib == NULL) {
2466         if (err_not_found) {
2467           PyErr_Format(PyExc_KeyError,
2468                        "%s: lib name '%.240s' "
2469                        "does not reference a valid library",
2470                        err_prefix,
2471                        keylib_str);
2472           return -1;
2473         }
2474         else {
2475           return 0;
2476         }
2477       }
2478     }
2479     else {
2480       PyErr_Format(PyExc_KeyError,
2481                    "%s: lib must be a string or None, not %.200s",
2482                    err_prefix,
2483                    Py_TYPE(keylib)->tp_name);
2484       return -1;
2485     }
2486
2487     /* lib is either a valid pointer or NULL,
2488      * either way can do direct comparison with id.lib */
2489
2490     RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) {
2491       ID *id = itemptr.data; /* Always an ID. */
2492       if (id->lib == lib && (STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2))) {
2493         found = true;
2494         if (r_ptr) {
2495           *r_ptr = itemptr;
2496         }
2497         break;
2498       }
2499     }
2500     RNA_PROP_END;
2501
2502     /* We may want to fail silently as with collection.get(). */
2503     if ((found == false) && err_not_found) {
2504       /* Only runs for getitem access so use fixed string. */
2505       PyErr_SetString(PyExc_KeyError, "bpy_prop_collection[key, lib]: not found");
2506       return -1;
2507     }
2508     else {
2509       return found; /* 1 / 0, no exception. */
2510     }
2511   }
2512 }
2513
2514 static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self,
2515                                                               PyObject *key,
2516                                                               const char *err_prefix,
2517                                                               const bool err_not_found)
2518 {
2519   PointerRNA ptr;
2520   const int contains = pyrna_prop_collection_subscript_str_lib_pair_ptr(
2521       self, key, err_prefix, err_not_found, &ptr);
2522
2523   if (contains == 1) {
2524     return pyrna_struct_CreatePyObject(&ptr);
2525   }
2526   else {
2527     return NULL;
2528   }
2529 }
2530
2531 static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self,
2532                                                        Py_ssize_t start,
2533                                                        Py_ssize_t stop)
2534 {
2535   CollectionPropertyIterator rna_macro_iter;
2536   int count;
2537
2538   PyObject *list;
2539   PyObject *item;
2540
2541   PYRNA_PROP_CHECK_OBJ(self);
2542
2543   list = PyList_New(0);
2544
2545   /* Skip to start. */
2546   RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter);
2547   RNA_property_collection_skip(&rna_macro_iter, start);
2548
2549   /* Add items until stop. */
2550   for (count = start; rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) {
2551     item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr);
2552     PyList_APPEND(list, item);
2553
2554     count++;
2555     if (count == stop) {
2556       break;
2557     }
2558   }
2559
2560   RNA_property_collection_end(&rna_macro_iter);
2561
2562   return list;
2563 }
2564
2565 /** TODO - dimensions
2566  * \note Could also use pyrna_prop_array_to_py_index(self, count) in a loop, but it's much slower
2567  * since at the moment it reads (and even allocates) the entire array for each index.
2568  */
2569 static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self,
2570                                                   PointerRNA *ptr,
2571                                                   PropertyRNA *prop,
2572                                                   Py_ssize_t start,
2573                                                   Py_ssize_t stop,
2574                                                   Py_ssize_t length)
2575 {
2576   int count, totdim;
2577   PyObject *tuple;
2578
2579   /* Isn't needed, internal use only. */
2580   // PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
2581
2582   tuple = PyTuple_New(stop - start);
2583
2584   totdim = RNA_property_array_dimension(ptr, prop, NULL);
2585
2586   if (totdim > 1) {
2587     for (count = start; count < stop; count++) {
2588       PyTuple_SET_ITEM(tuple, count - start, pyrna_prop_array_to_py_index(self, count));
2589     }
2590   }
2591   else {
2592     switch (RNA_property_type(prop)) {
2593       case PROP_FLOAT: {
2594         float values_stack[PYRNA_STACK_ARRAY];
2595         float *values;
2596         if (length > PYRNA_STACK_ARRAY) {
2597           values = PyMem_MALLOC(sizeof(float) * length);
2598         }
2599         else {
2600           values = values_stack;
2601         }
2602         RNA_property_float_get_array(ptr, prop, values);
2603
2604         for (count = start; count < stop; count++) {
2605           PyTuple_SET_ITEM(tuple, count - start, PyFloat_FromDouble(values[count]));
2606         }
2607
2608         if (values != values_stack) {
2609           PyMem_FREE(values);
2610         }
2611         break;
2612       }
2613       case PROP_BOOLEAN: {
2614         bool values_stack[PYRNA_STACK_ARRAY];
2615         bool *values;
2616         if (length > PYRNA_STACK_ARRAY) {
2617           values = PyMem_MALLOC(sizeof(bool) * length);
2618         }
2619         else {
2620           values = values_stack;
2621         }
2622
2623         RNA_property_boolean_get_array(ptr, prop, values);
2624         for (count = start; count < stop; count++) {
2625           PyTuple_SET_ITEM(tuple, count - start, PyBool_FromLong(values[count]));
2626         }
2627
2628         if (values != values_stack) {
2629           PyMem_FREE(values);
2630         }
2631         break;
2632       }
2633       case PROP_INT: {
2634         int values_stack[PYRNA_STACK_ARRAY];
2635         int *values;
2636         if (length > PYRNA_STACK_ARRAY) {
2637           values = PyMem_MALLOC(sizeof(int) * length);
2638         }
2639         else {
2640           values = values_stack;
2641         }
2642
2643         RNA_property_int_get_array(ptr, prop, values);
2644         for (count = start; count < stop; count++) {
2645           PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count]));
2646         }
2647
2648         if (values != values_stack) {
2649           PyMem_FREE(values);
2650         }
2651         break;
2652       }
2653       default:
2654         BLI_assert(!"Invalid array type");
2655
2656         PyErr_SetString(PyExc_TypeError, "not an array type");
2657         Py_DECREF(tuple);
2658         tuple = NULL;
2659         break;
2660     }
2661   }
2662   return tuple;
2663 }
2664
2665 static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject *key)
2666 {
2667   PYRNA_PROP_CHECK_OBJ(self);
2668
2669   if (PyUnicode_Check(key)) {
2670     return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key));
2671   }
2672   else if (PyIndex_Check(key)) {
2673     Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2674     if (i == -1 && PyErr_Occurred()) {
2675       return NULL;
2676     }
2677
2678     return pyrna_prop_collection_subscript_int(self, i);
2679   }
2680   else if (PySlice_Check(key)) {
2681     PySliceObject *key_slice = (PySliceObject *)key;
2682     Py_ssize_t step = 1;
2683
2684     if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2685       return NULL;
2686     }
2687     else if (step != 1) {
2688       PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported");
2689       return NULL;
2690     }
2691     else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2692       return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
2693     }
2694     else {
2695       Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
2696
2697       /* Avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
2698       if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
2699         return NULL;
2700       }
2701       if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
2702         return NULL;
2703       }
2704
2705       if (start < 0 || stop < 0) {
2706         /* Only get the length for negative values. */
2707         Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop);
2708         if (start < 0) {
2709           start += len;
2710         }
2711         if (stop < 0) {
2712           stop += len;
2713         }
2714       }
2715
2716       if (stop - start <= 0) {
2717         return PyList_New(0);
2718       }
2719       else {
2720         return pyrna_prop_collection_subscript_slice(self, start, stop);
2721       }
2722     }
2723   }
2724   else if (PyTuple_Check(key)) {
2725     /* Special case, for ID datablocks we. */
2726     return pyrna_prop_collection_subscript_str_lib_pair(
2727         self, key, "bpy_prop_collection[id, lib]", true);
2728   }
2729   else {
2730     PyErr_Format(PyExc_TypeError,
2731                  "bpy_prop_collection[key]: invalid key, "
2732                  "must be a string or an int, not %.200s",
2733                  Py_TYPE(key)->tp_name);
2734     return NULL;
2735   }
2736 }
2737
2738 /* generic check to see if a PyObject is compatible with a collection
2739  * -1 on failure, 0 on success, sets the error */
2740 static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *value)
2741 {
2742   StructRNA *prop_srna;
2743
2744   if (value == Py_None) {
2745     if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) {
2746       PyErr_Format(PyExc_TypeError,
2747                    "bpy_prop_collection[key] = value: invalid, "
2748                    "this collection doesn't support None assignment");
2749       return -1;
2750     }
2751     else {
2752       return 0; /* None is OK. */
2753     }
2754   }
2755   else if (BPy_StructRNA_Check(value) == 0) {
2756     PyErr_Format(PyExc_TypeError,
2757                  "bpy_prop_collection[key] = value: invalid, "
2758                  "expected a StructRNA type or None, not a %.200s",
2759                  Py_TYPE(value)->tp_name);
2760     return -1;
2761   }
2762   else if ((prop_srna = RNA_property_pointer_type(&self->ptr, self->prop))) {
2763     StructRNA *value_srna = ((BPy_StructRNA *)value)->ptr.type;
2764     if (RNA_struct_is_a(value_srna, prop_srna) == 0) {
2765       PyErr_Format(PyExc_TypeError,
2766                    "bpy_prop_collection[key] = value: invalid, "
2767                    "expected a '%.200s' type or None, not a '%.200s'",
2768                    RNA_struct_identifier(prop_srna),
2769                    RNA_struct_identifier(value_srna));
2770       return -1;
2771     }
2772     else {
2773       return 0; /* OK, this is the correct type! */
2774     }
2775   }
2776
2777   PyErr_Format(PyExc_TypeError,
2778                "bpy_prop_collection[key] = value: internal error, "
2779                "failed to get the collection type");
2780   return -1;
2781 }
2782
2783 /* note: currently this is a copy of 'pyrna_prop_collection_subscript' with
2784  * large blocks commented, we may support slice/key indices later */
2785 static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self,
2786                                                PyObject *key,
2787                                                PyObject *value)
2788 {
2789   PYRNA_PROP_CHECK_INT(self);
2790
2791   /* Validate the assigned value. */
2792   if (value == NULL) {
2793     PyErr_SetString(PyExc_TypeError, "del bpy_prop_collection[key]: not supported");
2794     return -1;
2795   }
2796   else if (pyrna_prop_collection_type_check(self, value) == -1) {
2797     return -1; /* Exception is set. */
2798   }
2799
2800 #if 0
2801   if (PyUnicode_Check(key)) {
2802     return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key));
2803   }
2804   else
2805 #endif
2806   if (PyIndex_Check(key)) {
2807     Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2808     if (i == -1 && PyErr_Occurred()) {
2809       return -1;
2810     }
2811
2812     return pyrna_prop_collection_ass_subscript_int(self, i, value);
2813   }
2814 #if 0 /* TODO, fake slice assignment. */
2815   else if (PySlice_Check(key)) {
2816     PySliceObject *key_slice = (PySliceObject *)key;
2817     Py_ssize_t step = 1;
2818
2819     if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2820       return NULL;
2821     }
2822     else if (step != 1) {
2823       PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported");
2824       return NULL;
2825     }
2826     else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2827       return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
2828     }
2829     else {
2830       Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
2831
2832       /* Avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
2833       if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
2834         return NULL;
2835       }
2836       if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
2837         return NULL;
2838       }
2839
2840       if (start < 0 || stop < 0) {
2841         /* Only get the length for negative values. */
2842         Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop);
2843         if (start < 0) {
2844           start += len;
2845         }
2846         if (stop < 0) {
2847           stop += len;
2848         }
2849       }
2850
2851       if (stop - start <= 0) {
2852         return PyList_New(0);
2853       }
2854       else {
2855         return pyrna_prop_collection_subscript_slice(self, start, stop);
2856       }
2857     }
2858   }
2859 #endif
2860   else {
2861     PyErr_Format(PyExc_TypeError,
2862                  "bpy_prop_collection[key]: invalid key, "
2863                  "must be a string or an int, not %.200s",
2864                  Py_TYPE(key)->tp_name);
2865     return -1;
2866   }
2867 }
2868
2869 static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject *key)
2870 {
2871   PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
2872
2873 #if 0
2874   if (PyUnicode_Check(key)) {
2875     return pyrna_prop_array_subscript_str(self, _PyUnicode_AsString(key));
2876   }
2877   else
2878 #endif
2879   if (PyIndex_Check(key)) {
2880     Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2881     if (i == -1 && PyErr_Occurred()) {
2882       return NULL;
2883     }
2884     return pyrna_prop_array_subscript_int(self, i);
2885   }
2886   else if (PySlice_Check(key)) {
2887     Py_ssize_t step = 1;
2888     PySliceObject *key_slice = (PySliceObject *)key;
2889
2890     if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2891       return NULL;
2892     }
2893     else if (step != 1) {
2894       PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported");
2895       return NULL;
2896     }
2897     else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2898       /* Note: no significant advantage with optimizing [:] slice as with collections,
2899        * but include here for consistency with collection slice func */
2900       Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self);
2901       return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len);
2902     }
2903     else {
2904       int len = pyrna_prop_array_length(self);
2905       Py_ssize_t start, stop, slicelength;
2906
2907       if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) {
2908         return NULL;
2909       }
2910
2911       if (slicelength <= 0) {
2912         return PyTuple_New(0);
2913       }
2914       else {
2915         return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, start, stop, len);
2916       }
2917     }
2918   }
2919   else {
2920     PyErr_SetString(PyExc_AttributeError, "bpy_prop_array[key]: invalid key, key must be an int");
2921     return NULL;
2922   }
2923 }
2924
2925 /**
2926  * Helpers for #prop_subscript_ass_array_slice
2927  */
2928
2929 static PyObject *prop_subscript_ass_array_slice__as_seq_fast(PyObject *value, int length)
2930 {
2931   PyObject *value_fast;
2932   if (!(value_fast = PySequence_Fast(value,
2933                                      "bpy_prop_array[slice] = value: "
2934                                      "element in assignment is not a sequence type"))) {
2935     return NULL;
2936   }
2937   else if (PySequence_Fast_GET_SIZE(value_fast) != length) {
2938     Py_DECREF(value_fast);
2939     PyErr_SetString(PyExc_ValueError,
2940                     "bpy_prop_array[slice] = value: "
2941                     "re-sizing bpy_struct element in arrays isn't supported");
2942
2943     return NULL;
2944   }
2945   else {
2946     return value_fast;
2947   }
2948 }
2949
2950 static int prop_subscript_ass_array_slice__float_recursive(
2951     PyObject **value_items, float *value, int totdim, const int dimsize[], const float range[2])
2952 {
2953   const int length = dimsize[0];
2954   if (totdim > 1) {
2955     int index = 0;
2956     int i;
2957     for (i = 0; i != length; i++) {
2958       PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]);
2959       if (UNLIKELY(subvalue == NULL)) {
2960         return 0;
2961       }
2962
2963       index += prop_subscript_ass_array_slice__float_recursive(
2964           PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range);
2965
2966       Py_DECREF(subvalue);
2967     }
2968     return index;
2969   }
2970   else {
2971     BLI_assert(totdim == 1);
2972     const float min = range[0], max = range[1];
2973     int i;
2974     for (i = 0; i != length; i++) {
2975       float v = PyFloat_AsDouble(value_items[i]);
2976       CLAMP(v, min, max);
2977       value[i] = v;
2978     }
2979     return i;
2980   }
2981 }
2982
2983 static int prop_subscript_ass_array_slice__int_recursive(
2984     PyObject **value_items, int *value, int totdim, const int dimsize[], const int range[2])
2985 {
2986   const int length = dimsize[0];
2987   if (totdim > 1) {
2988     int index = 0;
2989     int i;
2990     for (i = 0; i != length; i++) {
2991       PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]);
2992       if (UNLIKELY(subvalue == NULL)) {
2993         return 0;
2994       }
2995
2996       index += prop_subscript_ass_array_slice__int_recursive(
2997           PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range);
2998
2999       Py_DECREF(subvalue);
3000     }
3001     return index;
3002   }
3003   else {
3004     BLI_assert(totdim == 1);
3005     const int min = range[0], max = range[1];
3006     int i;
3007     for (i = 0; i != length; i++) {
3008       int v = PyLong_AsLong(value_items[i]);
3009       CLAMP(v, min, max);
3010       value[i] = v;
3011     }
3012     return i;
3013   }
3014 }
3015
3016 static int prop_subscript_ass_array_slice__bool_recursive(PyObject **value_items,
3017                                                           bool *value,
3018                                                           int totdim,
3019                                                           const int dimsize[])
3020 {
3021   const int length = dimsize[0];
3022   if (totdim > 1) {
3023     int index = 0;
3024     int i;
3025     for (i = 0; i != length; i++) {
3026       PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]);
3027       if (UNLIKELY(subvalue == NULL)) {
3028         return 0;
3029       }
3030
3031       index += prop_subscript_ass_array_slice__bool_recursive(
3032           PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1]);
3033
3034       Py_DECREF(subvalue);
3035     }
3036     return index;
3037   }
3038   else {
3039     BLI_assert(totdim == 1);
3040     int i;
3041     for (i = 0; i != length; i++) {
3042       int v = PyLong_AsLong(value_items[i]);
3043       value[i] = v;
3044     }
3045     return i;
3046   }
3047 }
3048
3049 /* Could call `pyrna_py_to_prop_array_index(self, i, value)` in a loop, but it is slow. */
3050 static int prop_subscript_ass_array_slice(PointerRNA *ptr,
3051                                           PropertyRNA *prop,
3052                                           int arraydim,
3053                                           int arrayoffset,
3054                                           int start,
3055                                           int stop,
3056                                           int length,
3057                                           PyObject *value_orig)
3058 {
3059   const int length_flat = RNA_property_array_length(ptr, prop);
3060   PyObject *value;
3061   PyObject **value_items;
3062   void *values_alloc = NULL;
3063   int ret = 0;
3064
3065   if (value_orig == NULL) {
3066     PyErr_SetString(
3067         PyExc_TypeError,
3068         "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct");
3069     return -1;
3070   }
3071
3072   if (!(value = PySequence_Fast(
3073             value_orig, "bpy_prop_array[slice] = value: assignment is not a sequence type"))) {
3074     return -1;
3075   }
3076
3077   if (PySequence_Fast_GET_SIZE(value) != stop - start) {
3078     Py_DECREF(value);
3079     PyErr_SetString(PyExc_TypeError,
3080                     "bpy_prop_array[slice] = value: re-sizing bpy_struct arrays isn't supported");
3081     return -1;
3082   }
3083
3084   int dimsize[3];
3085   int totdim = RNA_property_array_dimension(ptr, prop, dimsize);
3086   if (totdim > 1) {
3087     BLI_assert(dimsize[arraydim] == length);
3088   }
3089
3090   int span = 1;
3091   if (totdim > 1) {
3092     for (int i = arraydim + 1; i < totdim; i++) {
3093       span *= dimsize[i];
3094     }
3095   }
3096
3097   value_items = PySequence_Fast_ITEMS(value);
3098   switch (RNA_property_type(prop)) {
3099     case PROP_FLOAT: {
3100       float values_stack[PYRNA_STACK_ARRAY];
3101       float *values = (length_flat > PYRNA_STACK_ARRAY) ?
3102                           (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) :
3103                           values_stack;
3104       if (start != 0 || stop != length) {
3105         /* Partial assignment? - need to get the array. */
3106         RNA_property_float_get_array(ptr, prop, values);
3107       }
3108
3109       float range[2];
3110       RNA_property_float_range(ptr, prop, &range[0], &range[1]);
3111
3112       dimsize[arraydim] = stop - start;
3113       prop_subscript_ass_array_slice__float_recursive(value_items,
3114                                                       &values[arrayoffset + (start * span)],
3115                                                       totdim - arraydim,
3116                                                       &dimsize[arraydim],
3117                                                       range);
3118
3119       if (PyErr_Occurred()) {
3120         ret = -1;
3121       }
3122       else {
3123         RNA_property_float_set_array(ptr, prop, values);
3124       }
3125       break;
3126     }
3127     case PROP_INT: {
3128       int values_stack[PYRNA_STACK_ARRAY];
3129       int *values = (length_flat > PYRNA_STACK_ARRAY) ?
3130                         (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) :
3131                         values_stack;
3132       if (start != 0 || stop != length) {
3133         /* Partial assignment? - need to get the array. */
3134         RNA_property_int_get_array(ptr, prop, values);
3135       }
3136
3137       int range[2];
3138       RNA_property_int_range(ptr, prop, &range[0], &range[1]);
3139
3140       dimsize[arraydim] = stop - start;
3141       prop_subscript_ass_array_slice__int_recursive(value_items,
3142                                                     &values[arrayoffset + (start * span)],
3143                                                     totdim - arraydim,
3144                                                     &dimsize[arraydim],
3145                                                     range);
3146
3147       if (PyErr_Occurred()) {
3148         ret = -1;
3149       }
3150       else {
3151         RNA_property_int_set_array(ptr, prop, values);
3152       }
3153       break;
3154     }
3155     case PROP_BOOLEAN: {
3156       bool values_stack[PYRNA_STACK_ARRAY];
3157       bool *values = (length_flat > PYRNA_STACK_ARRAY) ?
3158                          (values_alloc = PyMem_MALLOC(sizeof(bool) * length_flat)) :
3159                          values_stack;
3160
3161       if (start != 0 || stop != length) {
3162         /* Partial assignment? - need to get the array. */
3163         RNA_property_boolean_get_array(ptr, prop, values);
3164       }
3165
3166       dimsize[arraydim] = stop - start;
3167       prop_subscript_ass_array_slice__bool_recursive(value_items,
3168                                                      &values[arrayoffset + (start * span)],
3169                                                      totdim - arraydim,
3170                                                      &dimsize[arraydim]);
3171
3172       if (PyErr_Occurred()) {
3173         ret = -1;
3174       }
3175       else {
3176         RNA_property_boolean_set_array(ptr, prop, values);
3177       }
3178       break;
3179     }
3180     default:
3181       PyErr_SetString(PyExc_TypeError, "not an array type");
3182       ret = -1;
3183       break;
3184   }
3185
3186   Py_DECREF(value);
3187
3188   if (values_alloc) {
3189     PyMem_FREE(values_alloc);
3190   }
3191
3192   return ret;
3193 }
3194
3195 static int prop_subscript_ass_array_int(BPy_PropertyArrayRNA *self,
3196                                         Py_ssize_t keynum,
3197                                         PyObject *value)
3198 {
3199   int len;
3200
3201   PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self);
3202
3203   len = pyrna_prop_array_length(self);
3204
3205   if (keynum < 0) {
3206     keynum += len;
3207   }
3208
3209   if (keynum >= 0 && keynum < len) {
3210     return pyrna_py_to_prop_array_index(self, keynum, value);
3211   }
3212
3213   PyErr_SetString(PyExc_IndexError, "bpy_prop_array[index] = value: index out of range");
3214   return -1;
3215 }
3216
3217 static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self,
3218                                           PyObject *key,
3219                                           PyObject *value)
3220 {
3221   // char *keyname = NULL; /* Not supported yet. */
3222   int ret = -1;
3223
3224   PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self);
3225
3226   if (!RNA_property_editable_flag(&self->ptr, self->prop)) {
3227     PyErr_Format(PyExc_AttributeError,
3228                  "bpy_prop_collection: attribute \"%.200s\" from \"%.200s\" is read-only",
3229                  RNA_property_identifier(self->prop),
3230                  RNA_struct_identifier(self->ptr.type));
3231     ret = -1;
3232   }
3233
3234   else if (PyIndex_Check(key)) {
3235     Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
3236     if (i == -1 && PyErr_Occurred()) {
3237       ret = -1;
3238     }
3239     else {
3240       ret = prop_subscript_ass_array_int(self, i, value);
3241     }
3242   }
3243   else if (PySlice_Check(key)) {
3244     Py_ssize_t len = pyrna_prop_array_length(self);
3245     Py_ssize_t start, stop, step, slicelength;
3246
3247     if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) {
3248       ret = -1;
3249     }
3250     else if (slicelength <= 0) {
3251       ret = 0; /* Do nothing. */
3252     }
3253     else if (step == 1) {
3254       ret = prop_subscript_ass_array_slice(
3255           &self->ptr, self->prop, self->arraydim, self->arrayoffset, start, stop, len, value);
3256     }
3257     else {
3258       PyErr_SetString(PyExc_TypeError, "slice steps not supported with RNA");
3259       ret = -1;
3260     }
3261   }
3262   else {
3263     PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int");
3264     ret = -1;
3265   }
3266
3267   if (ret != -1) {
3268     if (RNA_property_update_check(self->prop)) {
3269       RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
3270     }
3271   }
3272
3273   return ret;
3274 }
3275
3276 /* For slice only. */
3277 static PyMappingMethods pyrna_prop_array_as_mapping = {
3278     (lenfunc)pyrna_prop_array_length,              /* mp_length */
3279     (binaryfunc)pyrna_prop_array_subscript,        /* mp_subscript */
3280     (objobjargproc)pyrna_prop_array_ass_subscript, /* mp_ass_subscript */
3281 };
3282
3283 static PyMappingMethods pyrna_prop_collection_as_mapping = {
3284     (lenfunc)pyrna_prop_collection_length,              /* mp_length */
3285     (binaryfunc)pyrna_prop_collection_subscript,        /* mp_subscript */
3286     (objobjargproc)pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */
3287 };
3288
3289 /* Only for fast bool's, large structs, assign nb_bool on init. */
3290 static PyNumberMethods pyrna_prop_array_as_number = {
3291     NULL,                           /* nb_add */
3292     NULL,                           /* nb_subtract */
3293     NULL,                           /* nb_multiply */
3294     NULL,                           /* nb_remainder */
3295     NULL,                           /* nb_divmod */
3296     NULL,                           /* nb_power */
3297     NULL,                           /* nb_negative */
3298     NULL,                           /* nb_positive */
3299     NULL,                           /* nb_absolute */
3300     (inquiry)pyrna_prop_array_bool, /* nb_bool */
3301 };
3302 static PyNumberMethods pyrna_prop_collection_as_number = {
3303     NULL,                                /* nb_add */
3304     NULL,                                /* nb_subtract */
3305     NULL,                                /* nb_multiply */
3306     NULL,                                /* nb_remainder */
3307     NULL,                                /* nb_divmod */
3308     NULL,                                /* nb_power */
3309     NULL,                                /* nb_negative */
3310     NULL,                                /* nb_positive */
3311     NULL,                                /* nb_absolute */
3312     (inquiry)pyrna_prop_collection_bool, /* nb_bool */
3313 };
3314
3315 static int pyrna_prop_array_contains(BPy_PropertyRNA *self, PyObject *value)
3316 {
3317   return pyrna_array_contains_py(&self->ptr, self->prop, value);
3318 }
3319
3320 static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key)
3321 {
3322   PointerRNA newptr; /* Not used, just so RNA_property_collection_lookup_string runs. */
3323
3324   if (PyTuple_Check(key)) {
3325     /* Special case, for ID data-blocks. */
3326     return pyrna_prop_collection_subscript_str_lib_pair_ptr(
3327         self, key, "(id, lib) in bpy_prop_collection", false, NULL);
3328   }
3329   else {
3330
3331     /* Key in dict style check. */
3332     const char *keyname = _PyUnicode_AsString(key);
3333
3334     if (keyname == NULL) {
3335       PyErr_SetString(PyExc_TypeError,
3336                       "bpy_prop_collection.__contains__: expected a string or a tuple of strings");
3337       return -1;
3338     }
3339
3340     if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) {
3341       return 1;
3342     }
3343
3344     return 0;
3345   }
3346 }
3347
3348 static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value)
3349 {
3350   IDProperty *group;
3351   const char *name = _PyUnicode_AsString(value);
3352
3353   PYRNA_STRUCT_CHECK_INT(self);
3354
3355   if (!name) {
3356     PyErr_SetString(PyExc_TypeError, "bpy_struct.__contains__: expected a string");
3357     return -1;
3358   }
3359
3360   if (RNA_struct_idprops_check(self->ptr.type) == 0) {
3361     PyErr_SetString(PyExc_TypeError, "bpy_struct: this type doesn't support IDProperties");
3362     return -1;
3363   }
3364
3365   group = RNA_struct_idprops(&self->ptr, 0);
3366
3367   if (!group) {
3368     return 0;
3369   }
3370
3371   return IDP_GetPropertyFromGroup(group, name) ? 1 : 0;
3372 }
3373
3374 static PySequenceMethods pyrna_prop_array_as_sequence = {
3375     (lenfunc)pyrna_prop_array_length,
3376     NULL, /* sq_concat */
3377     NULL, /* sq_repeat */
3378     (ssizeargfunc)pyrna_prop_array_subscript_int,
3379     /* sq_item */ /* Only set this so PySequence_Check() returns True */
3380     NULL,         /* sq_slice */
3381     (ssizeobjargproc)prop_subscript_ass_array_int, /* sq_ass_item */
3382     NULL,                                          /* *was* sq_ass_slice */
3383     (objobjproc)pyrna_prop_array_contains,         /* sq_contains */
3384     (binaryfunc)NULL,                              /* sq_inplace_concat */
3385     (ssizeargfunc)NULL,                            /* sq_inplace_repeat */
3386 };
3387
3388 static PySequenceMethods pyrna_prop_collection_as_sequence = {
3389     (lenfunc)pyrna_prop_collection_length,
3390     NULL, /* sq_concat */
3391     NULL, /* sq_repeat */
3392     (ssizeargfunc)pyrna_prop_collection_subscript_int,
3393     /* sq_item */                         /* Only set this so PySequence_Check() returns True */
3394     NULL,                                 /* *was* sq_slice */
3395     (ssizeobjargproc)                     /* pyrna_prop_collection_ass_subscript_int */
3396     NULL /* let mapping take this one */, /* sq_ass_item */
3397     NULL,                                 /* *was* sq_ass_slice */
3398     (objobjproc)pyrna_prop_collection_contains, /* sq_contains */
3399     (binaryfunc)NULL,                           /* sq_inplace_concat */
3400     (ssizeargfunc)NULL,                         /* sq_inplace_repeat */
3401 };
3402
3403 static PySequenceMethods pyrna_struct_as_sequence = {
3404     NULL, /* Can't set the len otherwise it can evaluate as false */
3405     NULL, /* sq_concat */
3406     NULL, /* sq_repeat */
3407     NULL,
3408     /* sq_item */                      /* Only set this so PySequence_Check() returns True */
3409     NULL,                              /* *was* sq_slice */
3410     NULL,                              /* sq_ass_item */
3411     NULL,                              /* *was* sq_ass_slice */
3412     (objobjproc)pyrna_struct_contains, /* sq_contains */
3413     (binaryfunc)NULL,                  /* sq_inplace_concat */
3414     (ssizeargfunc)NULL,                /* sq_inplace_repeat */
3415 };
3416
3417 static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key)
3418 {
3419   /* Mostly copied from BPy_IDGroup_Map_GetItem. */
3420   IDProperty *group, *idprop;
3421   const char *name = _PyUnicode_AsString(key);
3422
3423   PYRNA_STRUCT_CHECK_OBJ(self);
3424
3425   if (RNA_struct_idprops_check(self->ptr.type) == 0) {
3426     PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties");
3427     return NULL;
3428   }
3429
3430   if (name == NULL) {
3431     PyErr_SetString(PyExc_TypeError,
3432                     "bpy_struct[key]: only strings are allowed as keys of ID properties");
3433     return NULL;
3434   }
3435
3436   group = RNA_struct_idprops(&self->ptr, 0);
3437
3438   if (group == NULL) {
3439     PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name);
3440     return NULL;
3441   }
3442
3443   idprop = IDP_GetPropertyFromGroup(group, name);
3444
3445   if (idprop == NULL) {
3446     PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name);
3447     return NULL;
3448   }
3449
3450   return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group);
3451 }
3452
3453 static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObject *value)
3454 {
3455   IDProperty *group;
3456
3457   PYRNA_STRUCT_CHECK_INT(self);
3458
3459   group = RNA_struct_idprops(&self->ptr, 1);
3460
3461 #ifdef USE_PEDANTIC_WRITE
3462   if (rna_disallow_writes && rna_id_write_error(&self->ptr, key)) {
3463     return -1;
3464   }
3465 #endif /* USE_PEDANTIC_WRITE */
3466
3467   if (group == NULL) {
3468     PyErr_SetString(PyExc_TypeError,
3469                     "bpy_struct[key] = val: id properties not supported for this type");
3470     return -1;
3471   }
3472
3473   if (value && BPy_StructRNA_Check(value)) {
3474     BPy_StructRNA *val = (BPy_StructRNA *)value;
3475     if (val && self->ptr.type && val->ptr.type) {
3476       if (!RNA_struct_idprops_datablock_allowed(self->ptr.type) &&
3477           RNA_struct_idprops_contains_datablock(val->ptr.type)) {
3478         PyErr_SetString(
3479             PyExc_TypeError,
3480             "bpy_struct[key] = val: datablock id properties not supported for this type");
3481         return -1;
3482       }
3483     }
3484   }
3485
3486   return BPy_Wrap_SetMapItem(group, key, value);
3487 }
3488
3489 static PyMappingMethods pyrna_struct_as_mapping = {
3490     (lenfunc)NULL,                             /* mp_length */
3491     (binaryfunc)pyrna_struct_subscript,        /* mp_subscript */
3492     (objobjargproc)pyrna_struct_ass_subscript, /* mp_ass_subscript */
3493 };
3494
3495 PyDoc_STRVAR(pyrna_struct_keys_doc,
3496              ".. method:: keys()\n"
3497              "\n"
3498              "   Returns the keys of this objects custom properties (matches Python's\n"
3499              "   dictionary function of the same name).\n"
3500              "\n"
3501              "   :return: custom property keys.\n"
3502              "   :rtype: list of strings\n"
3503              "\n" BPY_DOC_ID_PROP_TYPE_NOTE);
3504 static PyObject *pyrna_struct_keys(BPy_PropertyRNA *self)
3505 {
3506   IDProperty *group;
3507
3508   if (RNA_struct_idprops_check(self->ptr.type) == 0) {
3509     PyErr_SetString(PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties");
3510     return NULL;
3511   }
3512
3513   group = RNA_struct_idprops(&self->ptr, 0);
3514
3515   if (group == NULL) {
3516     return PyList_New(0);
3517   }
3518
3519   return BPy_Wrap_GetKeys(group);
3520 }
3521
3522 PyDoc_STRVAR(pyrna_struct_items_doc,
3523              ".. method:: items()\n"
3524              "\n"
3525              "   Returns the items of this objects custom properties (matches Python's\n"
3526              "   dictionary function of the same name).\n"
3527              "\n"
3528              "   :return: custom property key, value pairs.\n"
3529              "   :rtype: list of key, value tuples\n"
3530              "\n" BPY_DOC_ID_PROP_TYPE_NOTE);
3531 static PyObject *pyrna_struct_items(BPy_PropertyRNA *self)
3532 {
3533   IDProperty *group;
3534
3535   if (RNA_struct_idprops_check(self->ptr.type) == 0) {
3536     PyErr_SetString(PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties");
3537     return NULL;
3538   }
3539
3540   group = RNA_struct_idprops(&self->ptr, 0);
3541
3542   if (group == NULL) {
3543     return PyList_New(0);
3544   }
3545
3546   return BPy_Wrap_GetItems(self->ptr.id.data, group);
3547 }
3548
3549 PyDoc_STRVAR(pyrna_struct_values_doc,
3550              ".. method:: values()\n"
3551              "\n"
3552              "   Returns the values of this objects custom properties (matches Python's\n"
3553              "   dictionary function of the same name).\n"
3554              "\n"
3555              "   :return: custom property values.\n"
3556              "   :rtype: list\n"
3557              "\n" BPY_DOC_ID_PROP_TYPE_NOTE);
3558 static PyObject *pyrna_struct_values(BPy_PropertyRNA *self)
3559 {
3560   IDProperty *group;
3561
3562   if (RNA_struct_idprops_check(self->ptr.type) == 0) {
3563     PyErr_SetString(PyExc_TypeError,
3564                     "bpy_struct.values(): this type doesn't support IDProperties");
3565     return NULL;
3566   }
3567
3568   group = RNA_struct_idprops(&self->ptr, 0);
3569
3570   if (group == NULL) {
3571     return PyList_New(0);
3572   }
3573
3574   return BPy_Wrap_GetValues(self->ptr.id.data, group);
3575 }
3576
3577 PyDoc_STRVAR(pyrna_struct_is_property_set_doc,
3578              ".. method:: is_property_set(property)\n"
3579              "\n"
3580              "   Check if a property is set, use for testing operator properties.\n"
3581              "\n"
3582              "   :return: True when the property has been set.\n"
3583              "   :rtype: boolean\n");
3584 static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args)
3585 {
3586   PropertyRNA *prop;
3587   const char *name;
3588
3589   PYRNA_STRUCT_CHECK_OBJ(self);
3590
3591   if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) {
3592     return NULL;
3593   }
3594
3595   if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
3596     PyErr_Format(PyExc_TypeError,
3597                  "%.200s.is_property_set(\"%.200s\") not found",
3598                  RNA_struct_identifier(self->ptr.type),
3599                  name);
3600     return NULL;
3601   }
3602
3603   return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop));
3604 }
3605
3606 PyDoc_STRVAR(pyrna_struct_property_unset_doc,
3607              ".. method:: property_unset(property)\n"
3608              "\n"
3609              "   Unset a property, will use default value afterward.\n");
3610 static PyObject *pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args)
3611 {
3612   PropertyRNA *prop;
3613   const char *name;
3614
3615   PYRNA_STRUCT_CHECK_OBJ(self);
3616
3617   if (!PyArg_ParseTuple(args, "s:property_unset", &name)) {
3618     return NULL;
3619   }
3620
3621   if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
3622     PyErr_Format(PyExc_TypeError,
3623                  "%.200s.property_unset(\"%.200s\") not found",
3624                  RNA_struct_identifier(self->ptr.type),
3625                  name);
3626     return NULL;
3627   }
3628
3629   RNA_property_unset(&self->ptr, prop);
3630
3631   Py_RETURN_NONE;
3632 }
3633
3634 PyDoc_STRVAR(pyrna_struct_is_property_hidden_doc,
3635              ".. method:: is_property_hidden(property)\n"
3636              "\n"
3637              "   Check if a property is hidden.\n"
3638              "\n"
3639              "   :return: True when the property is hidden.\n"