Blender V5.0
bpy_rna.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
14
15#include <Python.h>
16
17#include <cfloat> /* FLT_MIN/MAX */
18#include <cstddef>
19#include <optional>
20
21#include "RNA_path.hh"
22#include "RNA_types.hh"
23
24#include "BLI_dynstr.h"
25#include "BLI_listbase.h"
26#include "BLI_math_rotation.h"
27#include "BLI_path_utils.hh"
28#include "BLI_string.h"
29#include "BLI_string_utf8.h"
30#include "BLI_utildefines.h"
31#include "BLI_vector.hh"
32
33#include "BPY_extern.hh"
34#include "BPY_extern_clog.hh"
35
36#include "bpy_capi_utils.hh"
37#include "bpy_intern_string.hh"
38#include "bpy_props.hh"
39#include "bpy_rna.hh"
40#include "bpy_rna_anim.hh"
41#include "bpy_rna_callback.hh"
42
43#ifdef USE_PYRNA_INVALIDATE_WEAKREF
44# include "BLI_ghash.h"
45#endif
46
47#include "RNA_access.hh"
48#include "RNA_define.hh" /* RNA_def_property_free_identifier */
49#include "RNA_enum_types.hh"
50#include "RNA_prototypes.hh"
51
52#include "CLG_log.h"
53
54#include "MEM_guardedalloc.h"
55
57
58#include "BKE_context.hh"
59#include "BKE_global.hh" /* evil G.* */
60#include "BKE_idprop.hh"
61#include "BKE_idtype.hh"
62#include "BKE_main.hh"
63#include "BKE_report.hh"
64
65/* Only for types. */
66#include "BKE_node.hh"
67
69
70#include "../generic/idprop_py_api.hh" /* For IDprop lookups. */
74#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
76
77#define USE_PEDANTIC_WRITE
78#define USE_MATHUTILS
79#define USE_STRING_COERCE
80
88#define USE_POSTPONED_ANNOTATIONS
89
90/* Unfortunately Python needs to hold a global reference to the context.
91 * If we remove this is means `bpy.context` won't be usable from some parts of the code:
92 * `bpy.app.handler` callbacks for example.
93 * Even though this is arguably "correct", it's going to cause problems for existing scripts,
94 * so accept having this for the time being. */
95
96BPy_StructRNA *bpy_context_module = nullptr; /* for fast access */
97
102static const char *BPy_capsule_PointerRNA_identifier = "BPy_PointerRNA_PyCapsule";
103
109
114static const char *BPy_PropertyPointerRNA_capsule_identifier = "BPy_PropertyPointerRNA_PyCapsule";
115
119static PyObject *pyrna_func_CreatePyObject(const PointerRNA *ptr, FunctionRNA *func);
120
122 PyTypeObject *tp,
123 void **instance);
124
125static PyObject *pyrna_srna_Subtype(StructRNA *srna);
126static PyObject *pyrna_struct_Subtype(PointerRNA *ptr);
128
129static PyObject *pyrna_register_class(PyObject *self, PyObject *py_class);
130static PyObject *pyrna_unregister_class(PyObject *self, PyObject *py_class);
131
133
138#define BPY_DOC_ID_PROP_TYPE_NOTE \
139 " .. note::\n" \
140 "\n" \
141 " Limited to: :ref:`bpy_types-custom_properties`.\n"
142
144{
145 if (pysrna->ptr->type) {
146 return 0;
147 }
148 return -1;
149}
150
152{
153 PyErr_Format(
154 PyExc_ReferenceError, "StructRNA of type %.200s has been removed", Py_TYPE(pysrna)->tp_name);
155}
156
158{
159 if (pysrna->ptr->type) {
160 return 0;
161 }
163 return -1;
164}
165
167{
168 if (self->ptr->type) {
169 return 0;
170 }
171 PyErr_Format(PyExc_ReferenceError,
172 "PropertyRNA of type %.200s.%.200s has been removed",
173 Py_TYPE(self)->tp_name,
175 return -1;
176}
177
179{
180 self->ptr->invalidate();
181}
182
184 const PropertyRNA *prop,
185 const DeprecatedRNA *deprecated)
186{
187 PyErr_WarnFormat(PyExc_DeprecationWarning,
188 1,
189 "'%s.%s' is expected to be removed in Blender %d.%d",
192 deprecated->removal_version / 100,
193 deprecated->removal_version % 100,
194 deprecated->note);
195}
196
197#ifdef USE_PYRNA_INVALIDATE_GC
198# define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g) + 1))
199
200/* Only for sizeof(). */
201struct gc_generation {
202 PyGC_Head head;
203 int threshold;
204 int count;
205} gc_generation;
206
207static void id_release_gc(struct ID *id)
208{
209 uint j;
210 // uint i = 0;
211 for (j = 0; j < 3; j++) {
212 /* Hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed. */
213 PyGC_Head *gen = (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j));
214 PyGC_Head *g = gen->gc.gc_next;
215 while ((g = g->gc.gc_next) != gen) {
216 PyObject *ob = FROM_GC(g);
217 if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) ||
218 PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type))
219 {
221 if (ob_ptr->ptr->owner_id == id) {
222 pyrna_invalidate(ob_ptr);
223 // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name);
224 // i++;
225 }
226 }
227 }
228 }
229 // printf("id_release_gc freed '%s': %d\n", id->name, i);
230}
231#endif
232
233#ifdef USE_PYRNA_INVALIDATE_WEAKREF
234// #define DEBUG_RNA_WEAKREF
235
236struct GHash *id_weakref_pool = nullptr;
237static PyObject *id_free_weakref_cb(PyObject *weakinfo_pair, PyObject *weakref);
238static PyMethodDef id_free_weakref_cb_def = {
239 "id_free_weakref_cb", (PyCFunction)id_free_weakref_cb, METH_O, nullptr};
240
244static void id_weakref_pool_free_value_fn(void *p)
245{
246 GHash *weakinfo_hash = static_cast<GHash *>(p);
247 BLI_ghash_free(weakinfo_hash, nullptr, nullptr);
248}
249
250/* Adds a reference to the list, remember to decref. */
251static GHash *id_weakref_pool_get(ID *id)
252{
253 GHash *weakinfo_hash = static_cast<GHash *>(BLI_ghash_lookup(id_weakref_pool, (void *)id));
254 if (weakinfo_hash == nullptr) {
255 /* This could be a set, values are used to keep a reference back to the ID
256 * (all of them are the same). */
257 weakinfo_hash = BLI_ghash_ptr_new("rna_id");
258 BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash);
259 }
260 return weakinfo_hash;
261}
262
263/* Called from pyrna_struct_CreatePyObject() and pyrna_prop_CreatePyObject(). */
264static void id_weakref_pool_add(ID *id, BPy_DummyPointerRNA *pyrna)
265{
266 PyObject *weakref;
267 PyObject *weakref_capsule;
268 PyObject *weakref_cb_py;
269
270 /* Create a new function instance and insert the list as 'self'
271 * so we can remove ourself from it. */
272 GHash *weakinfo_hash = id_weakref_pool_get(id); /* New or existing. */
273
274 weakref_capsule = PyCapsule_New(weakinfo_hash, nullptr, nullptr);
275 weakref_cb_py = PyCFunction_New(&id_free_weakref_cb_def, weakref_capsule);
276 Py_DECREF(weakref_capsule);
277
278 /* Add weakref to weakinfo_hash list. */
279 weakref = PyWeakref_NewRef((PyObject *)pyrna, weakref_cb_py);
280
281 Py_DECREF(weakref_cb_py); /* Function owned by the weakref now. */
282
283 /* Important to add at the end of the hash, since first removal looks at the end. */
284
285 /* Using a hash table as a set, all 'id's are the same. */
286 BLI_ghash_insert(weakinfo_hash, weakref, id);
287 /* weakinfo_hash owns the weakref */
288}
289
290/* Workaround to get the last id without a lookup. */
291static ID *_id_tmp_ptr;
292static void value_id_set(void *id)
293{
294 _id_tmp_ptr = (ID *)id;
295}
296
297static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash);
298static PyObject *id_free_weakref_cb(PyObject *weakinfo_pair, PyObject *weakref)
299{
300 /* Important to search backwards. */
301 GHash *weakinfo_hash = static_cast<GHash *>(PyCapsule_GetPointer(weakinfo_pair, nullptr));
302
303 if (BLI_ghash_len(weakinfo_hash) > 1) {
304 BLI_ghash_remove(weakinfo_hash, weakref, nullptr, nullptr);
305 }
306 else { /* Get the last id and free it. */
307 BLI_ghash_remove(weakinfo_hash, weakref, nullptr, value_id_set);
308 id_release_weakref_list(_id_tmp_ptr, weakinfo_hash);
309 }
310
311 Py_DECREF(weakref);
312
313 Py_RETURN_NONE;
314}
315
316static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash)
317{
318 GHashIterator weakinfo_hash_iter;
319
320 BLI_ghashIterator_init(&weakinfo_hash_iter, weakinfo_hash);
321
322# ifdef DEBUG_RNA_WEAKREF
323 fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_len(weakinfo_hash));
324# endif
325
326 while (!BLI_ghashIterator_done(&weakinfo_hash_iter)) {
327 PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter);
328 PyObject *item = PyWeakref_GET_OBJECT(weakref);
329 if (item != Py_None) {
330
331# ifdef DEBUG_RNA_WEAKREF
332 PyC_ObSpit("id_release_weakref item ", item);
333# endif
334
336 }
337
338 Py_DECREF(weakref);
339
340 BLI_ghashIterator_step(&weakinfo_hash_iter);
341 }
342
343 BLI_ghash_remove(id_weakref_pool, (void *)id, nullptr, nullptr);
344 BLI_ghash_free(weakinfo_hash, nullptr, nullptr);
345}
346
347static void id_release_weakref(struct ID *id)
348{
349 GHash *weakinfo_hash = static_cast<GHash *>(BLI_ghash_lookup(id_weakref_pool, (void *)id));
350 if (weakinfo_hash) {
351 id_release_weakref_list(id, weakinfo_hash);
352 }
353}
354
355#endif /* USE_PYRNA_INVALIDATE_WEAKREF */
356
358 PyObject *(*nameprop_as_py_object_fn)(const char *, Py_ssize_t);
360};
361
367{
368 char fixedbuf[256];
369 int name_len;
370 PropertyRNA *nameprop;
371 char *name_ptr = RNA_struct_name_get_alloc_ex(
372 ptr, fixedbuf, sizeof(fixedbuf), &name_len, &nameprop);
373 if (LIKELY(name_ptr)) {
374 /* In most cases this only runs once. */
375 if (UNLIKELY(nameprop != nameprop_cache.nameprop)) {
376 nameprop_cache.nameprop = nameprop;
377 const PropertySubType subtype = RNA_property_subtype(nameprop);
380 }
381 else {
382 nameprop_cache.nameprop_as_py_object_fn = PyUnicode_FromStringAndSize;
383 }
384 }
385 PyObject *result = nameprop_cache.nameprop_as_py_object_fn(name_ptr, name_len);
386 /* The string data may be corrupt if this asserts,
387 * or not using a file-path sub-type when it should.. */
388 BLI_assert(result != nullptr);
389 if (name_ptr != fixedbuf) {
390 MEM_freeN(name_ptr);
391 }
392 return result;
393 }
394 return nullptr;
395}
396
398{
399#ifdef USE_PYRNA_INVALIDATE_GC
400 id_release_gc(id);
401#endif
402
403#ifdef USE_PYRNA_INVALIDATE_WEAKREF
404 /* Check for nullptr since this may run before Python has been started. */
405 if (id_weakref_pool != nullptr) {
406 PyGILState_STATE gilstate = PyGILState_Ensure();
407
408 id_release_weakref(id);
409
410 PyGILState_Release(gilstate);
411 }
412#endif /* USE_PYRNA_INVALIDATE_WEAKREF */
413
414 (void)id;
415}
416
417#ifdef USE_PEDANTIC_WRITE
418static bool rna_disallow_writes = false;
419
420static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
421{
422 ID *id = ptr->owner_id;
423 if (id) {
424 const short idcode = GS(id->name);
425 /* May need more ID types added here. */
426 if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) {
427 const char *idtype = BKE_idtype_idcode_to_name(idcode);
428 const char *pyname;
429 if (key && PyUnicode_Check(key)) {
430 pyname = PyUnicode_AsUTF8(key);
431 }
432 else {
433 pyname = "<UNKNOWN>";
434 }
435
436 /* Make a nice string error. */
437 BLI_assert(idtype != nullptr);
438 PyErr_Format(PyExc_AttributeError,
439 "Writing to ID classes in this context is not allowed: "
440 "%.200s, %.200s data-block, error setting %.200s.%.200s",
441 id->name + 2,
442 idtype,
444 pyname);
445
446 return true;
447 }
448 }
449 return false;
450}
451#endif /* USE_PEDANTIC_WRITE */
452
453#ifdef USE_PEDANTIC_WRITE
454
455/* NOTE: Without the GIL, this can cause problems when called from threads, see: #127767. */
456
458{
459 BLI_assert(PyGILState_Check());
460
461 return !rna_disallow_writes;
462}
463
464void pyrna_write_set(bool val)
465{
466 BLI_assert(PyGILState_Check());
467
468 rna_disallow_writes = !val;
469}
470#else /* USE_PEDANTIC_WRITE */
472{
473 BLI_assert(PyGILState_Check());
474
475 return true;
476}
477void pyrna_write_set(bool /*val*/)
478{
479 BLI_assert(PyGILState_Check());
480
481 /* pass */
482}
483#endif /* USE_PEDANTIC_WRITE */
484
487static int pyrna_py_to_prop(
488 PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix);
489static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item);
490
491#ifdef USE_MATHUTILS
492# include "../mathutils/mathutils.hh" /* So we can have mathutils callbacks. */
493
496 PropertyRNA *prop,
497 Py_ssize_t start,
498 Py_ssize_t stop,
499 Py_ssize_t length);
501 const short order_fallback,
502 PropertyRNA **r_prop_eul_order);
503
504/* `bpyrna` vector/euler/quaternion callbacks. */
505static uchar mathutils_rna_array_cb_index = -1; /* Index for our callbacks. */
506
507/* Sub-type not used much yet. */
508# define MATHUTILS_CB_SUBTYPE_EUL 0
509# define MATHUTILS_CB_SUBTYPE_VEC 1
510# define MATHUTILS_CB_SUBTYPE_QUAT 2
511# define MATHUTILS_CB_SUBTYPE_COLOR 3
512
514{
515 BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
516
518
519 return self->prop ? 0 : -1;
520}
521
522static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype)
523{
524 BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
525
527
528 if (self->prop == nullptr) {
529 return -1;
530 }
531
532 RNA_property_float_get_array(&self->ptr.value(), self->prop, bmo->data);
533
534 /* Euler order exception. */
535 if (subtype == MATHUTILS_CB_SUBTYPE_EUL) {
536 EulerObject *eul = (EulerObject *)bmo;
537 PropertyRNA *prop_eul_order = nullptr;
538 eul->order = pyrna_rotation_euler_order_get(&self->ptr.value(), eul->order, &prop_eul_order);
539 }
540
541 return 0;
542}
543
544static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype)
545{
546 BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
547 float min, max;
548
550
551 if (self->prop == nullptr) {
552 return -1;
553 }
554
555# ifdef USE_PEDANTIC_WRITE
556 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), nullptr)) {
557 return -1;
558 }
559# endif /* USE_PEDANTIC_WRITE */
560
561 if (!RNA_property_editable_flag(&self->ptr.value(), self->prop)) {
562 PyErr_Format(PyExc_AttributeError,
563 "bpy_prop \"%.200s.%.200s\" is read-only",
564 RNA_struct_identifier(self->ptr->type),
566 return -1;
567 }
568
569 RNA_property_float_range(&self->ptr.value(), self->prop, &min, &max);
570
571 if (min != -FLT_MAX || max != FLT_MAX) {
572 int i, len = RNA_property_array_length(&self->ptr.value(), self->prop);
573 for (i = 0; i < len; i++) {
574 CLAMP(bmo->data[i], min, max);
575 }
576 }
577
578 RNA_property_float_set_array(&self->ptr.value(), self->prop, bmo->data);
579 if (RNA_property_update_check(self->prop)) {
580 RNA_property_update(BPY_context_get(), &self->ptr.value(), self->prop);
581 }
582
583 /* Euler order exception. */
584 if (subtype == MATHUTILS_CB_SUBTYPE_EUL) {
585 EulerObject *eul = (EulerObject *)bmo;
586 PropertyRNA *prop_eul_order = nullptr;
587 const short order = pyrna_rotation_euler_order_get(
588 &self->ptr.value(), eul->order, &prop_eul_order);
589 if (order != eul->order) {
590 RNA_property_enum_set(&self->ptr.value(), prop_eul_order, eul->order);
591 if (RNA_property_update_check(prop_eul_order)) {
592 RNA_property_update(BPY_context_get(), &self->ptr.value(), prop_eul_order);
593 }
594 }
595 }
596 return 0;
597}
598
599static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int /*subtype*/, int index)
600{
601 BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
602
604
605 if (self->prop == nullptr) {
606 return -1;
607 }
608
609 bmo->data[index] = RNA_property_float_get_index(&self->ptr.value(), self->prop, index);
610 return 0;
611}
612
613static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int /*subtype*/, int index)
614{
615 BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
616
618
619 if (self->prop == nullptr) {
620 return -1;
621 }
622
623# ifdef USE_PEDANTIC_WRITE
624 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), nullptr)) {
625 return -1;
626 }
627# endif /* USE_PEDANTIC_WRITE */
628
629 if (!RNA_property_editable_flag(&self->ptr.value(), self->prop)) {
630 PyErr_Format(PyExc_AttributeError,
631 "bpy_prop \"%.200s.%.200s\" is read-only",
632 RNA_struct_identifier(self->ptr->type),
634 return -1;
635 }
636
637 RNA_property_float_clamp(&self->ptr.value(), self->prop, &bmo->data[index]);
638 RNA_property_float_set_index(&self->ptr.value(), self->prop, index, bmo->data[index]);
639
640 if (RNA_property_update_check(self->prop)) {
641 RNA_property_update(BPY_context_get(), &self->ptr.value(), self->prop);
642 }
643
644 return 0;
645}
646
654
655/* BPY/RNA matrix callbacks. */
656static uchar mathutils_rna_matrix_cb_index = -1; /* Index for our callbacks. */
657
658static int mathutils_rna_matrix_get(BaseMathObject *bmo, int /*subtype*/)
659{
660 BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
661
663
664 if (self->prop == nullptr) {
665 return -1;
666 }
667
668 RNA_property_float_get_array(&self->ptr.value(), self->prop, bmo->data);
669 return 0;
670}
671
672static int mathutils_rna_matrix_set(BaseMathObject *bmo, int /*subtype*/)
673{
674 BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user;
675
677
678 if (self->prop == nullptr) {
679 return -1;
680 }
681
682# ifdef USE_PEDANTIC_WRITE
683 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), nullptr)) {
684 return -1;
685 }
686# endif /* USE_PEDANTIC_WRITE */
687
688 if (!RNA_property_editable_flag(&self->ptr.value(), self->prop)) {
689 PyErr_Format(PyExc_AttributeError,
690 "bpy_prop \"%.200s.%.200s\" is read-only",
691 RNA_struct_identifier(self->ptr->type),
693 return -1;
694 }
695
696 /* Can ignore clamping here. */
697 RNA_property_float_set_array(&self->ptr.value(), self->prop, bmo->data);
698
699 if (RNA_property_update_check(self->prop)) {
700 RNA_property_update(BPY_context_get(), &self->ptr.value(), self->prop);
701 }
702 return 0;
703}
704
712
714 const short order_fallback,
715 PropertyRNA **r_prop_eul_order)
716{
717 /* Attempt to get order. */
718 if (*r_prop_eul_order == nullptr) {
719 *r_prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode");
720 }
721
722 if (*r_prop_eul_order) {
723 const short order = RNA_property_enum_get(ptr, *r_prop_eul_order);
724 /* Could be quaternion or axis-angle. */
725 if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) {
726 return order;
727 }
728 }
729
730 return order_fallback;
731}
732
733#endif /* USE_MATHUTILS */
734
739#define PROP_ALL_VECTOR_SUBTYPES \
740 PROP_COORDS: \
741 case PROP_TRANSLATION: \
742 case PROP_DIRECTION: \
743 case PROP_VELOCITY: \
744 case PROP_ACCELERATION: \
745 case PROP_XYZ: \
746 case PROP_XYZ_LENGTH
747
749{
750 PyObject *ret = nullptr;
751
752#ifdef USE_MATHUTILS
753 int subtype, totdim;
754 int len;
755 const int flag = RNA_property_flag(prop);
756 const int type = RNA_property_type(prop);
757 const bool is_thick = (flag & PROP_THICK_WRAP) != 0;
758
759 /* disallow dynamic sized arrays to be wrapped since the size could change
760 * to a size mathutils does not support */
761 if (flag & PROP_DYNAMIC) {
762 return nullptr;
763 }
764
766 if (type == PROP_FLOAT) {
767 /* pass */
768 }
769 else if (type == PROP_INT) {
770 if (is_thick) {
771 goto thick_wrap_slice;
772 }
773 else {
774 return nullptr;
775 }
776 }
777 else {
778 return nullptr;
779 }
780
781 subtype = RNA_property_subtype(prop);
782 totdim = RNA_property_array_dimension(ptr, prop, nullptr);
783
784 if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) {
785 if (!is_thick) {
786 /* Owned by the mathutils PyObject. */
788 }
789
790 switch (subtype) {
792 if (len >= 2 && len <= 4) {
793 if (is_thick) {
794 ret = Vector_CreatePyObject(nullptr, len, nullptr);
796 }
797 else {
798 PyObject *vec_cb = Vector_CreatePyObject_cb(
800 Py_DECREF(ret); /* The vector owns 'ret' now. */
801 ret = vec_cb; /* Return the vector instead. */
802 }
803 }
804 break;
805 case PROP_MATRIX:
806 if (len == 16) {
807 if (is_thick) {
808 ret = Matrix_CreatePyObject(nullptr, 4, 4, nullptr);
810 }
811 else {
812 PyObject *mat_cb = Matrix_CreatePyObject_cb(
814 Py_DECREF(ret); /* The matrix owns 'ret' now. */
815 ret = mat_cb; /* Return the matrix instead. */
816 }
817 }
818 else if (len == 9) {
819 if (is_thick) {
820 ret = Matrix_CreatePyObject(nullptr, 3, 3, nullptr);
822 }
823 else {
824 PyObject *mat_cb = Matrix_CreatePyObject_cb(
826 Py_DECREF(ret); /* The matrix owns 'ret' now. */
827 ret = mat_cb; /* Return the matrix instead. */
828 }
829 }
830 break;
831 case PROP_EULER:
832 case PROP_QUATERNION:
833 if (len == 3) { /* Euler. */
834 if (is_thick) {
835 /* Attempt to get order,
836 * only needed for thick types since wrapped with update via callbacks. */
837 PropertyRNA *prop_eul_order = nullptr;
838 const short order = pyrna_rotation_euler_order_get(
839 ptr, EULER_ORDER_XYZ, &prop_eul_order);
840
841 ret = Euler_CreatePyObject(nullptr, order, nullptr); /* TODO: get order from RNA. */
843 }
844 else {
845 /* Order will be updated from callback on use. */
846 /* TODO: get order from RNA. */
847 PyObject *eul_cb = Euler_CreatePyObject_cb(
849 Py_DECREF(ret); /* The euler owns 'ret' now. */
850 ret = eul_cb; /* Return the euler instead. */
851 }
852 }
853 else if (len == 4) {
854 if (is_thick) {
855 ret = Quaternion_CreatePyObject(nullptr, nullptr);
857 }
858 else {
859 PyObject *quat_cb = Quaternion_CreatePyObject_cb(
861 Py_DECREF(ret); /* The quat owns 'ret' now. */
862 ret = quat_cb; /* Return the quat instead. */
863 }
864 }
865 break;
866 case PROP_COLOR:
867 case PROP_COLOR_GAMMA:
868 if (len == 3) { /* Color. */
869 if (is_thick) {
870 ret = Color_CreatePyObject(nullptr, nullptr);
872 }
873 else {
874 PyObject *col_cb = Color_CreatePyObject_cb(
876 Py_DECREF(ret); /* The color owns 'ret' now. */
877 ret = col_cb; /* Return the color instead. */
878 }
879 }
880 break;
881 default:
882 break;
883 }
884 }
885
886 if (ret == nullptr) {
887 if (is_thick) {
888 /* This is an array we can't reference (since it is not thin wrappable)
889 * and cannot be coerced into a mathutils type, so return as a list. */
890 thick_wrap_slice:
891 ret = pyrna_prop_array_subscript_slice(nullptr, ptr, prop, 0, len, len);
892 }
893 else {
894 ret = pyrna_prop_CreatePyObject(ptr, prop); /* Owned by the mathutils PyObject. */
895 }
896 }
897#else /* USE_MATHUTILS */
898 (void)ptr;
899 (void)prop;
900#endif /* USE_MATHUTILS */
901
902 return ret;
903}
904
905/* NOTE(@ideasman42): Regarding comparison `__cmp__`:
906 * checking the 'ptr->data' matches works in almost all cases,
907 * however there are a few RNA properties that are fake sub-structs and
908 * share the pointer with the parent, in those cases this happens 'a.b == a'
909 * see: r43352 for example.
910 *
911 * So compare the 'ptr->type' as well to avoid this problem.
912 * It's highly unlikely this would happen that 'ptr->data' and 'ptr->prop' would match,
913 * but _not_ 'ptr->type' but include this check for completeness. */
914
916{
917 return (((a->ptr->data == b->ptr->data) && (a->ptr->type == b->ptr->type)) ? 0 : -1);
918}
919
921{
922 return (
923 ((a->prop == b->prop) && (a->ptr->data == b->ptr->data) && (a->ptr->type == b->ptr->type)) ?
924 0 :
925 -1);
926}
927
928static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op)
929{
930 PyObject *res;
931 int ok = -1; /* Zero is true. */
932
935 }
936
937 switch (op) {
938 case Py_NE:
939 ok = !ok;
941 case Py_EQ:
942 res = ok ? Py_False : Py_True;
943 break;
944
945 case Py_LT:
946 case Py_LE:
947 case Py_GT:
948 case Py_GE:
949 res = Py_NotImplemented;
950 break;
951 default:
952 PyErr_BadArgument();
953 return nullptr;
954 }
955
956 return Py_NewRef(res);
957}
958
959static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
960{
961 PyObject *res;
962 int ok = -1; /* Zero is true. */
963
966 }
967
968 switch (op) {
969 case Py_NE:
970 ok = !ok;
972 case Py_EQ:
973 res = ok ? Py_False : Py_True;
974 break;
975
976 case Py_LT:
977 case Py_LE:
978 case Py_GT:
979 case Py_GE:
980 res = Py_NotImplemented;
981 break;
982 default:
983 PyErr_BadArgument();
984 return nullptr;
985 }
986
987 return Py_NewRef(res);
988}
989
990/*----------------------repr--------------------------------------------*/
992{
993 PyObject *ret;
994 const char *name;
995 const char *extra_info = "";
996
998 return PyUnicode_FromFormat("<bpy_struct, %.200s invalid>", Py_TYPE(self)->tp_name);
999 }
1000
1001 ID *id = self->ptr->owner_id;
1002 if (id && id != DEG_get_original(id)) {
1003 extra_info = ", evaluated";
1004 }
1005
1006 /* Print name if available.
1007 *
1008 * Always include the pointer address since it can help identify unique data,
1009 * or when data is re-allocated internally. */
1010 name = RNA_struct_name_get_alloc(&self->ptr.value(), nullptr, 0, nullptr);
1011 if (name) {
1012 ret = PyUnicode_FromFormat("<bpy_struct, %.200s(\"%.200s\") at %p%s>",
1013 RNA_struct_identifier(self->ptr->type),
1014 name,
1015 self->ptr->data,
1016 extra_info);
1017 MEM_freeN(name);
1018 return ret;
1019 }
1020
1021 return PyUnicode_FromFormat("<bpy_struct, %.200s at %p%s>",
1022 RNA_struct_identifier(self->ptr->type),
1023 self->ptr->data,
1024 extra_info);
1025}
1026
1028{
1029 ID *id = self->ptr->owner_id;
1030 PyObject *tmp_str;
1031 PyObject *ret;
1032
1033 if (id == nullptr || !PYRNA_STRUCT_IS_VALID(self) || (DEG_get_original(id) != id)) {
1034 /* fallback */
1035 return pyrna_struct_str(self);
1036 }
1037
1038 tmp_str = PyUnicode_FromString(id->name + 2);
1039
1040 if (RNA_struct_is_ID(self->ptr->type) && (id->flag & ID_FLAG_EMBEDDED_DATA) == 0) {
1041 ret = PyUnicode_FromFormat(
1042 "bpy.data.%s[%R]", BKE_idtype_idcode_to_name_plural(GS(id->name)), tmp_str);
1043 }
1044 else {
1045 ID *real_id = nullptr;
1046 const std::optional<std::string> path = RNA_path_from_real_ID_to_struct(
1047 G_MAIN, &self->ptr.value(), &real_id);
1048 if (path) {
1049 /* 'real_id' may be nullptr in some cases, although the only valid one is evaluated data,
1050 * which should have already been caught above.
1051 * So assert, but handle it without crashing for release builds. */
1052 BLI_assert(real_id != nullptr);
1053
1054 if (real_id != nullptr) {
1055 Py_DECREF(tmp_str);
1056 tmp_str = PyUnicode_FromString(real_id->name + 2);
1057 ret = PyUnicode_FromFormat("bpy.data.%s[%R].%s",
1059 tmp_str,
1060 path->c_str());
1061 }
1062 else {
1063 /* Can't find the path, print something useful as a fallback. */
1064 ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s",
1066 tmp_str,
1067 RNA_struct_identifier(self->ptr->type));
1068 }
1069 }
1070 else {
1071 /* Can't find the path, print something useful as a fallback. */
1072 ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s",
1074 tmp_str,
1075 RNA_struct_identifier(self->ptr->type));
1076 }
1077 }
1078
1079 Py_DECREF(tmp_str);
1080
1081 return ret;
1082}
1083
1085{
1086 PyObject *ret;
1088 const char *name;
1089 const char *type_id = nullptr;
1090 char type_lower[64];
1091 char type_count[16];
1092 int type;
1093
1095
1096 type = RNA_property_type(self->prop);
1097
1098 if (RNA_enum_id_from_value(rna_enum_property_type_items, type, &type_id) == 0) {
1099 /* Should never happen. */
1100 PyErr_SetString(PyExc_RuntimeError, "could not use property type, internal error");
1101 return nullptr;
1102 }
1103
1104 STRNCPY_UTF8(type_lower, type_id);
1105 BLI_str_tolower_ascii(type_lower, sizeof(type_lower));
1106
1107 int len = -1;
1108 if (type == PROP_COLLECTION) {
1110 }
1111 else if (RNA_property_array_check(self->prop)) {
1113 }
1114
1115 if (len != -1) {
1116 SNPRINTF_UTF8(type_count, "[%d]", len);
1117 }
1118 else {
1119 type_count[0] = '\0';
1120 }
1121
1122 /* If a pointer, try to print name of pointer target too. */
1123 if (type == PROP_POINTER) {
1124 ptr = RNA_property_pointer_get(&self->ptr.value(), self->prop);
1125 name = RNA_struct_name_get_alloc(&ptr, nullptr, 0, nullptr);
1126
1127 if (name) {
1128 ret = PyUnicode_FromFormat("<bpy_%.200s%.200s, %.200s.%.200s(\"%.200s\")>",
1129 type_lower,
1130 type_count,
1131 RNA_struct_identifier(self->ptr->type),
1133 name);
1134 MEM_freeN(name);
1135 return ret;
1136 }
1137 }
1138 if (type == PROP_COLLECTION) {
1139 PointerRNA r_ptr;
1140 if (RNA_property_collection_type_get(&self->ptr.value(), self->prop, &r_ptr)) {
1141 return PyUnicode_FromFormat(
1142 "<bpy_%.200s%.200s, %.200s>", type_lower, type_count, RNA_struct_identifier(r_ptr.type));
1143 }
1144 }
1145
1146 return PyUnicode_FromFormat("<bpy_%.200s%.200s, %.200s.%.200s>",
1147 type_lower,
1148 type_count,
1149 RNA_struct_identifier(self->ptr->type),
1151}
1152
1153static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, const int index)
1154{
1155 ID *id = self->ptr->owner_id;
1156 PyObject *tmp_str;
1157 PyObject *ret;
1158
1160
1161 if (id == nullptr) {
1162 /* Fallback. */
1163 return pyrna_prop_str(self);
1164 }
1165
1166 tmp_str = PyUnicode_FromString(id->name + 2);
1167
1168 /* Note that using G_MAIN is absolutely not ideal, but we have no access to actual Main DB from
1169 * here. */
1170 ID *real_id = nullptr;
1171 const std::optional<std::string> path = RNA_path_from_real_ID_to_property_index(
1172 G_MAIN, &self->ptr.value(), self->prop, index_dim, index, &real_id);
1173
1174 if (path) {
1175 if (real_id != id) {
1176 Py_DECREF(tmp_str);
1177 tmp_str = PyUnicode_FromString(real_id->name + 2);
1178 }
1179 const char *data_delim = ((*path)[0] == '[') ? "" : ".";
1180 ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s",
1182 tmp_str,
1183 data_delim,
1184 path->c_str());
1185 }
1186 else {
1187 /* Can't find the path, print something useful as a fallback. */
1188 ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s",
1190 tmp_str,
1192 }
1193
1194 Py_DECREF(tmp_str);
1195
1196 return ret;
1197}
1198
1200{
1201 return pyrna_prop_repr_ex(self, 0, -1);
1202}
1203
1205{
1206 return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset);
1207}
1208
1210{
1211 return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>",
1212 Py_TYPE(self)->tp_name,
1213 RNA_struct_identifier(self->ptr->type),
1215}
1216
1218{
1219 return Py_HashPointer(self->ptr->data);
1220}
1221
1222/* From Python's meth_hash v3.1.2. */
1224{
1225 long x, y;
1226 if (self->ptr->data == nullptr) {
1227 x = 0;
1228 }
1229 else {
1230 x = Py_HashPointer(self->ptr->data);
1231 if (x == -1) {
1232 return -1;
1233 }
1234 }
1235 y = Py_HashPointer((void *)(self->prop));
1236 if (y == -1) {
1237 return -1;
1238 }
1239 x ^= y;
1240 if (x == -1) {
1241 x = -2;
1242 }
1243 return x;
1244}
1245
1246#ifdef USE_PYRNA_STRUCT_REFERENCE
1247static int pyrna_struct_traverse(BPy_StructRNA *self, visitproc visit, void *arg)
1248{
1249 Py_VISIT(self->reference);
1250 return 0;
1251}
1252
1253static int pyrna_struct_clear(BPy_StructRNA *self)
1254{
1255 Py_CLEAR(self->reference);
1256 return 0;
1257}
1258#endif /* !USE_PYRNA_STRUCT_REFERENCE */
1259
1260#ifdef USE_PYRNA_STRUCT_REFERENCE
1261static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference)
1262{
1263 if (self->reference) {
1264 PyObject_GC_UnTrack(self);
1265 Py_CLEAR(self->reference);
1266 }
1267 /* Reference is now nullptr. */
1268
1269 if (reference) {
1270 self->reference = reference;
1271 Py_INCREF(reference);
1272 BLI_assert(!PyObject_GC_IsTracked((PyObject *)self));
1273 PyObject_GC_Track(self);
1274 }
1275}
1276#endif /* !USE_PYRNA_STRUCT_REFERENCE */
1277
1279{
1280 const EnumPropertyItem *item;
1281 const char *result;
1282 bool free = false;
1283
1284 RNA_property_enum_items(BPY_context_get(), ptr, prop, &item, nullptr, &free);
1285 if (item) {
1286 result = pyrna_enum_repr(item);
1287 }
1288 else {
1289 result = "";
1290 }
1291
1292 if (free) {
1293 MEM_freeN(item);
1294 }
1295
1296 return result;
1297}
1298
1300 PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, const char *error_prefix)
1301{
1302 const char *param = PyUnicode_AsUTF8(item);
1303
1304 if (param == nullptr) {
1305 PyErr_Format(PyExc_TypeError,
1306 "%.200s expected a string enum, not %.200s",
1307 error_prefix,
1308 Py_TYPE(item)->tp_name);
1309 return -1;
1310 }
1311
1312 if (!RNA_property_enum_value(BPY_context_get(), ptr, prop, param, r_value)) {
1313 const char *enum_str = pyrna_enum_as_string(ptr, prop);
1314 PyErr_Format(PyExc_TypeError,
1315 "%.200s enum \"%.200s\" not found in (%s)",
1316 error_prefix,
1317 param,
1318 enum_str);
1319 MEM_freeN(enum_str);
1320 return -1;
1321 }
1322
1323 return 0;
1324}
1325
1327 PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, const char *error_prefix)
1328{
1329 const EnumPropertyItem *item;
1330 int ret;
1331 bool free = false;
1332
1333 *r_value = 0;
1334
1335 if (!PyAnySet_Check(value)) {
1336 PyErr_Format(PyExc_TypeError,
1337 "%.200s, %.200s.%.200s expected a set, not a %.200s",
1338 error_prefix,
1341 Py_TYPE(value)->tp_name);
1342 return -1;
1343 }
1344
1345 RNA_property_enum_items(BPY_context_get(), ptr, prop, &item, nullptr, &free);
1346
1347 if (item) {
1348 ret = pyrna_enum_bitfield_from_set(item, value, r_value, error_prefix);
1349 }
1350 else {
1351 if (PySet_GET_SIZE(value)) {
1352 PyErr_Format(PyExc_TypeError,
1353 "%.200s: empty enum \"%.200s\" could not have any values assigned",
1354 error_prefix,
1356 ret = -1;
1357 }
1358 else {
1359 ret = 0;
1360 }
1361 }
1362
1363 if (free) {
1364 MEM_freeN(item);
1365 }
1366
1367 return ret;
1368}
1369
1370static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
1371{
1372 PyObject *item, *ret = nullptr;
1373
1374 if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
1375 const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1];
1376
1377 ret = PySet_New(nullptr);
1378
1379 if (RNA_property_enum_bitflag_identifiers(BPY_context_get(), ptr, prop, val, identifier)) {
1380 int index;
1381
1382 for (index = 0; identifier[index]; index++) {
1383 item = PyUnicode_FromString(identifier[index]);
1384 PySet_Add(ret, item);
1385 Py_DECREF(item);
1386 }
1387 }
1388 }
1389 else {
1390 const char *identifier;
1391 if (RNA_property_enum_identifier(BPY_context_get(), ptr, prop, val, &identifier)) {
1392 ret = PyUnicode_FromString(identifier);
1393 }
1394 else {
1395 /* Static, no need to free. */
1396 const EnumPropertyItem *enum_item;
1397 bool free_dummy;
1398 RNA_property_enum_items_ex(nullptr, ptr, prop, true, &enum_item, nullptr, &free_dummy);
1399 BLI_assert(!free_dummy);
1400
1401 /* Do not print warning in case of #rna_enum_dummy_NULL_items,
1402 * this one will never match any value... */
1403 if (enum_item != rna_enum_dummy_NULL_items) {
1404 const char *ptr_name = RNA_struct_name_get_alloc(ptr, nullptr, 0, nullptr);
1405
1406 /* Prefer not to fail silently in case of API errors, maybe disable it later. */
1408 "current value '%d' "
1409 "matches no enum in '%s', '%s', '%s'",
1410 val,
1412 ptr_name,
1414
1415#if 0 /* Gives Python decoding errors while generating docs :( */
1416 char error_str[256];
1417 BLI_snprintf_utf8(error_str,
1418 sizeof(error_str),
1419 "RNA Warning: Current value \"%d\" "
1420 "matches no enum in '%s', '%s', '%s'",
1421 val,
1423 ptr_name,
1425
1426 PyErr_Warn(PyExc_RuntimeWarning, error_str);
1427#endif
1428
1429 if (ptr_name) {
1430 MEM_freeN(ptr_name);
1431 }
1432 }
1433
1434 ret = PyUnicode_FromString("");
1435#if 0
1436 PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val);
1437 ret = nullptr;
1438#endif
1439 }
1440 }
1441
1442 return ret;
1443}
1444
1446{
1447 PyObject *ret;
1448 const int type = RNA_property_type(prop);
1449
1450 if (const DeprecatedRNA *deprecated = RNA_property_deprecated(prop)) {
1451 pyrna_prop_warn_deprecated(ptr, prop, deprecated);
1452 }
1453
1454 if (RNA_property_array_check(prop)) {
1455 return pyrna_py_from_array(ptr, prop);
1456 }
1457
1458 /* See if we can coerce into a Python type - 'PropertyType'. */
1459 switch (type) {
1460 case PROP_BOOLEAN:
1461 ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop));
1462 break;
1463 case PROP_INT:
1464 ret = PyLong_FromLong(RNA_property_int_get(ptr, prop));
1465 break;
1466 case PROP_FLOAT:
1467 ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop));
1468 break;
1469 case PROP_STRING: {
1470 const int subtype = RNA_property_subtype(prop);
1471 const char *buf;
1472 int buf_len;
1473 char buf_fixed[32];
1474
1475 buf = RNA_property_string_get_alloc(ptr, prop, buf_fixed, sizeof(buf_fixed), &buf_len);
1476#ifdef USE_STRING_COERCE
1477 /* Only file paths get special treatment, they may contain non UTF8 chars. */
1478 if (subtype == PROP_BYTESTRING) {
1479 ret = PyBytes_FromStringAndSize(buf, buf_len);
1480 }
1481 else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
1482 ret = PyC_UnicodeFromBytesAndSize(buf, buf_len);
1483 }
1484 else {
1485 ret = PyUnicode_FromStringAndSize(buf, buf_len);
1486 }
1487#else /* USE_STRING_COERCE */
1488 if (subtype == PROP_BYTESTRING) {
1489 ret = PyBytes_FromStringAndSize(buf, buf_len);
1490 }
1491 else {
1492 ret = PyUnicode_FromStringAndSize(buf, buf_len);
1493 }
1494#endif /* USE_STRING_COERCE */
1495 if (buf_fixed != buf) {
1496 MEM_freeN(buf);
1497 }
1498 break;
1499 }
1500 case PROP_ENUM: {
1502 break;
1503 }
1504 case PROP_POINTER: {
1505 PointerRNA newptr;
1506 newptr = RNA_property_pointer_get(ptr, prop);
1507 if (newptr.data) {
1509 }
1510 else {
1511 ret = Py_None;
1512 Py_INCREF(ret);
1513 }
1514 break;
1515 }
1516 case PROP_COLLECTION:
1518 break;
1519 default:
1520 PyErr_Format(PyExc_TypeError,
1521 "bpy_struct internal error: unknown type '%d' (pyrna_prop_to_py)",
1522 type);
1523 ret = nullptr;
1524 break;
1525 }
1526
1527 return ret;
1528}
1529
1531 PyObject *kw,
1532 const bool all_args,
1533 const char *error_prefix)
1534{
1535 int error_val = 0;
1536 int totkw;
1537 const char *arg_name = nullptr;
1538 PyObject *item;
1539
1540 totkw = kw ? PyDict_Size(kw) : 0;
1541
1542 RNA_STRUCT_BEGIN (ptr, prop) {
1543 arg_name = RNA_property_identifier(prop);
1544
1545 if (STREQ(arg_name, "rna_type")) {
1546 continue;
1547 }
1548
1549 if (kw == nullptr) {
1550 PyErr_Format(
1551 PyExc_TypeError, "%.200s: no keywords, expected \"%.200s\"", error_prefix, arg_name);
1552 error_val = -1;
1553 break;
1554 }
1555
1556 item = PyDict_GetItemString(kw, arg_name); /* Won't set an error. */
1557
1558 if (item == nullptr) {
1559 if (all_args) {
1560 PyErr_Format(PyExc_TypeError,
1561 "%.200s: keyword \"%.200s\" missing",
1562 error_prefix,
1563 arg_name ? arg_name : "<UNKNOWN>");
1564 error_val = -1; /* pyrna_py_to_prop sets the error. */
1565 break;
1566 }
1567 }
1568 else {
1569 if (pyrna_py_to_prop(ptr, prop, nullptr, item, error_prefix)) {
1570 error_val = -1;
1571 break;
1572 }
1573 totkw--;
1574 }
1575 }
1577
1578 if (error_val == 0 && totkw > 0) { /* Some keywords were given that were not used :/. */
1579 PyObject *key, *value;
1580 Py_ssize_t pos = 0;
1581
1582 while (PyDict_Next(kw, &pos, &key, &value)) {
1583 arg_name = PyUnicode_AsUTF8(key);
1584 if (RNA_struct_find_property(ptr, arg_name) == nullptr) {
1585 break;
1586 }
1587 arg_name = nullptr;
1588 }
1589
1590 PyErr_Format(PyExc_TypeError,
1591 "%.200s: keyword \"%.200s\" unrecognized",
1592 error_prefix,
1593 arg_name ? arg_name : "<UNKNOWN>");
1594 error_val = -1;
1595 }
1596
1597 return error_val;
1598}
1599
1601 PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix)
1602{
1603 /* XXX hard limits should be checked here. */
1604 const int type = RNA_property_type(prop);
1605
1606 if (const DeprecatedRNA *deprecated = RNA_property_deprecated(prop)) {
1607 pyrna_prop_warn_deprecated(ptr, prop, deprecated);
1608 }
1609
1610 if (RNA_property_array_check(prop)) {
1611 /* Done getting the length. */
1612 if (pyrna_py_to_array(ptr, prop, static_cast<char *>(data), value, error_prefix) == -1) {
1613 return -1;
1614 }
1615 }
1616 else {
1617 /* Normal Property (not an array). */
1618
1619 /* See if we can coerce into a Python type - 'PropertyType'. */
1620 switch (type) {
1621 case PROP_BOOLEAN: {
1622 int param;
1623 /* Prefer not to have an exception here
1624 * however so many poll functions return None or a valid Object.
1625 * It's a hassle to convert these into a bool before returning. */
1626 if (RNA_parameter_flag(prop) & PARM_OUTPUT) {
1627 param = PyObject_IsTrue(value);
1628 }
1629 else {
1630 param = PyC_Long_AsI32(value);
1631
1632 if (UNLIKELY(param & ~1)) { /* Only accept 0/1. */
1633 param = -1; /* Error out below. */
1634 }
1635 }
1636
1637 if (param == -1) {
1638 PyErr_Format(PyExc_TypeError,
1639 "%.200s %.200s.%.200s expected True/False or 0/1, not %.200s",
1640 error_prefix,
1643 Py_TYPE(value)->tp_name);
1644 return -1;
1645 }
1646
1647 if (data) {
1648 *((bool *)data) = param;
1649 }
1650 else {
1651 RNA_property_boolean_set(ptr, prop, param);
1652 }
1653
1654 break;
1655 }
1656 case PROP_INT: {
1657 int overflow;
1658 const long param = PyLong_AsLongAndOverflow(value, &overflow);
1659 if (overflow || (param > INT_MAX) || (param < INT_MIN)) {
1660 PyErr_Format(PyExc_ValueError,
1661 "%.200s %.200s.%.200s value not in 'int' range "
1662 "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")",
1663 error_prefix,
1666 return -1;
1667 }
1668 if (param == -1 && PyErr_Occurred()) {
1669 PyErr_Format(PyExc_TypeError,
1670 "%.200s %.200s.%.200s expected an int type, not %.200s",
1671 error_prefix,
1674 Py_TYPE(value)->tp_name);
1675 return -1;
1676 }
1677
1678 int param_i = int(param);
1679 if (data) {
1680 RNA_property_int_clamp(ptr, prop, &param_i);
1681 *((int *)data) = param_i;
1682 }
1683 else {
1684 RNA_property_int_set(ptr, prop, param_i);
1685 }
1686
1687 break;
1688 }
1689 case PROP_FLOAT: {
1690 const float param = PyFloat_AsDouble(value);
1691 if (PyErr_Occurred()) {
1692 PyErr_Format(PyExc_TypeError,
1693 "%.200s %.200s.%.200s expected a float type, not %.200s",
1694 error_prefix,
1697 Py_TYPE(value)->tp_name);
1698 return -1;
1699 }
1700
1701 if (data) {
1702 RNA_property_float_clamp(ptr, prop, (float *)&param);
1703 *((float *)data) = param;
1704 }
1705 else {
1706 RNA_property_float_set(ptr, prop, param);
1707 }
1708
1709 break;
1710 }
1711 case PROP_STRING: {
1712 const int flag = RNA_property_flag(prop);
1713 const int subtype = RNA_property_subtype(prop);
1714 const char *param;
1715
1716 if (value == Py_None) {
1717 if ((flag & PROP_NEVER_NULL) == 0) {
1718 if (data) {
1719 if (flag & PROP_THICK_WRAP) {
1720 *(char *)data = 0;
1721 }
1722 else {
1723 *((char **)data) = (char *)nullptr;
1724 }
1725 }
1726 else {
1727 RNA_property_string_set(ptr, prop, nullptr);
1728 }
1729 }
1730 else {
1731 PyErr_Format(PyExc_TypeError,
1732 "%.200s %.200s.%.200s doesn't support None from string types",
1733 error_prefix,
1736 return -1;
1737 }
1738 }
1739 else if (subtype == PROP_BYTESTRING) {
1740
1741 /* Byte String. */
1742
1743 param = PyBytes_AsString(value);
1744
1745 if (param == nullptr) {
1746 if (PyBytes_Check(value)) {
1747 /* there was an error assigning a string type,
1748 * rather than setting a new error, prefix the existing one
1749 */
1750 PyC_Err_Format_Prefix(PyExc_TypeError,
1751 "%.200s %.200s.%.200s error assigning bytes",
1752 error_prefix,
1755 }
1756 else {
1757 PyErr_Format(PyExc_TypeError,
1758 "%.200s %.200s.%.200s expected a bytes type, not %.200s",
1759 error_prefix,
1762 Py_TYPE(value)->tp_name);
1763 }
1764
1765 return -1;
1766 }
1767
1768 if (data) {
1769 if (flag & PROP_THICK_WRAP) {
1770 BLI_strncpy((char *)data, param, RNA_property_string_maxlength(prop));
1771 }
1772 else {
1773 *((char **)data) = (char *)param;
1774 }
1775 }
1776 else {
1777 RNA_property_string_set_bytes(ptr, prop, param, PyBytes_Size(value));
1778 }
1779 }
1780 else {
1781/* Unicode String. */
1782#ifdef USE_STRING_COERCE
1783 PyObject *value_coerce = nullptr;
1784 if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
1785 /* TODO: get size. */
1786 param = PyC_UnicodeAsBytes(value, &value_coerce);
1787 }
1788 else {
1789 param = PyUnicode_AsUTF8(value);
1790 }
1791#else /* USE_STRING_COERCE */
1792 param = PyUnicode_AsUTF8(value);
1793#endif /* USE_STRING_COERCE */
1794
1795 if (param == nullptr) {
1796 if (PyUnicode_Check(value)) {
1797 /* there was an error assigning a string type,
1798 * rather than setting a new error, prefix the existing one
1799 */
1800 PyC_Err_Format_Prefix(PyExc_TypeError,
1801 "%.200s %.200s.%.200s error assigning string",
1802 error_prefix,
1805 }
1806 else {
1807 PyErr_Format(PyExc_TypeError,
1808 "%.200s %.200s.%.200s expected a string type, not %.200s",
1809 error_prefix,
1812 Py_TYPE(value)->tp_name);
1813 }
1814
1815 return -1;
1816 }
1817
1819 if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) {
1820 if (BLI_path_is_rel(param)) {
1821 char warning_buf[256];
1822 SNPRINTF_UTF8(warning_buf,
1823 "%.200s.%.200s: does not support blend relative \"//\" prefix",
1826 PyErr_WarnEx(PyExc_RuntimeWarning, warning_buf, 1);
1827 }
1828 }
1829 }
1830
1831 /* Same as bytes (except for UTF8 string copy). */
1832 /* XXX, this is suspect, but needed for function calls,
1833 * need to see if there's a better way. */
1834 if (data) {
1835 if (flag & PROP_THICK_WRAP) {
1837 }
1838 else {
1839 *((char **)data) = (char *)param;
1840 }
1841 }
1842 else {
1843 RNA_property_string_set(ptr, prop, param);
1844 }
1845
1846#ifdef USE_STRING_COERCE
1847 Py_XDECREF(value_coerce);
1848#endif /* USE_STRING_COERCE */
1849 }
1850 break;
1851 }
1852 case PROP_ENUM: {
1853 int val = 0;
1854
1855 /* Type checking is done by each function. */
1856 if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
1857 /* Set of enum items, concatenate all values with OR. */
1858 if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) == -1) {
1859 return -1;
1860 }
1861 }
1862 else {
1863 /* Simple enum string. */
1864 if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) == -1) {
1865 return -1;
1866 }
1867 }
1868
1869 if (data) {
1870 *((int *)data) = val;
1871 }
1872 else {
1873 RNA_property_enum_set(ptr, prop, val);
1874 }
1875
1876 break;
1877 }
1878 case PROP_POINTER: {
1879 PyObject *value_new = nullptr;
1880
1881 StructRNA *ptr_type = RNA_property_pointer_type(ptr, prop);
1882 const int flag = RNA_property_flag(prop);
1883 const int flag_parameter = RNA_parameter_flag(prop);
1884
1885 /* This is really nasty! Done so we can fake the operator having direct properties, eg:
1886 * layout.prop(self, "filepath")
1887 * ... which in fact should be:
1888 * layout.prop(self.properties, "filepath")
1889 *
1890 * we need to do this trick.
1891 * if the prop is not an operator type and the PyObject is an operator,
1892 * use its properties in place of itself.
1893 *
1894 * This is so bad that it is almost a good reason to do away with fake
1895 * 'self.properties -> self'
1896 * class mixing. If this causes problems in the future it should be removed.
1897 */
1898 if ((ptr_type == &RNA_AnyType) && BPy_StructRNA_Check(value)) {
1899 const StructRNA *base_type = RNA_struct_base_child_of(
1900 ((const BPy_StructRNA *)value)->ptr->type, nullptr);
1901 if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) {
1902 value = PyObject_GetAttr(value, bpy_intern_str_properties);
1903 value_new = value;
1904 }
1905 }
1906
1907 /* if property is an OperatorProperties/GizmoProperties pointer and value is a map,
1908 * forward back to pyrna_pydict_to_props */
1909 if (PyDict_Check(value)) {
1910 const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, nullptr);
1911 if (ELEM(base_type, &RNA_OperatorProperties, &RNA_GizmoProperties)) {
1913 if (opptr.type) {
1914 return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
1915 }
1916 /* Converting a dictionary to properties is not supported
1917 * for function arguments, this would be nice to support but is complicated
1918 * because the operator type needs to be read from another function argument
1919 * and allocated data needs to be freed. See #135245. */
1920
1921 /* This is only expected to happen for RNA functions. */
1922 BLI_assert(ptr->type == &RNA_Function);
1923 if (ptr->type != &RNA_Function) {
1924 PyErr_Format(PyExc_TypeError,
1925 "%.200s %.200s.%.200s internal error coercing a dict for %.200s type",
1926 error_prefix,
1929 RNA_struct_identifier(ptr_type));
1930 return -1;
1931 }
1932 }
1933 }
1934
1935 /* Another exception, allow passing a collection as an RNA property. */
1936 if (Py_TYPE(value) == &pyrna_prop_collection_Type) { /* Ok to ignore idprop collections. */
1937 PointerRNA c_ptr;
1938 BPy_PropertyRNA *value_prop = (BPy_PropertyRNA *)value;
1939 if (RNA_property_collection_type_get(&value_prop->ptr.value(), value_prop->prop, &c_ptr))
1940 {
1941 value = pyrna_struct_CreatePyObject(&c_ptr);
1942 value_new = value;
1943 }
1944 else {
1945 PyErr_Format(PyExc_TypeError,
1946 "%.200s %.200s.%.200s collection has no type, "
1947 "cannot be used as a %.200s type",
1948 error_prefix,
1951 RNA_struct_identifier(ptr_type));
1952 return -1;
1953 }
1954 }
1955
1956 BPy_StructRNA *param;
1957 if (value == Py_None) {
1958 if (flag & PROP_NEVER_NULL) {
1959 PyErr_Format(PyExc_TypeError,
1960 "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type",
1961 error_prefix,
1964 RNA_struct_identifier(ptr_type));
1965 Py_XDECREF(value_new);
1966 return -1;
1967 }
1968 param = nullptr;
1969 }
1970 else {
1971 if (!BPy_StructRNA_Check(value)) {
1972 PyErr_Format(PyExc_TypeError,
1973 "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
1974 error_prefix,
1977 RNA_struct_identifier(ptr_type),
1978 Py_TYPE(value)->tp_name);
1979 Py_XDECREF(value_new);
1980 return -1;
1981 }
1982 param = (BPy_StructRNA *)value;
1983
1984 const ID *value_owner_id = ((BPy_StructRNA *)value)->ptr->owner_id;
1985 if (value_owner_id != nullptr) {
1986 if ((flag & PROP_ID_SELF_CHECK) && (ptr->owner_id == value_owner_id)) {
1987 PyErr_Format(PyExc_TypeError,
1988 "%.200s %.200s.%.200s ID type does not support assignment to itself",
1989 error_prefix,
1992 Py_XDECREF(value_new);
1993 return -1;
1994 }
1995
1996 if (value_owner_id->tag & ID_TAG_TEMP_MAIN) {
1997 /* Allow passing temporary ID's to functions, but not attribute assignment. */
1998 if (ptr->type != &RNA_Function) {
1999 PyErr_Format(PyExc_TypeError,
2000 "%.200s %.200s.%.200s ID type assignment is temporary, cannot assign",
2001 error_prefix,
2004 Py_XDECREF(value_new);
2005 return -1;
2006 }
2007 }
2008 }
2009 }
2010
2011 bool raise_error = false;
2012 if (data) {
2013
2014 if (flag_parameter & PARM_RNAPTR) {
2015 if (flag & PROP_THICK_WRAP) {
2016 if (param == nullptr) {
2017 *reinterpret_cast<PointerRNA *>(data) = {};
2018 }
2019 else if (RNA_struct_is_a(param->ptr->type, ptr_type)) {
2020 *reinterpret_cast<PointerRNA *>(data) = *param->ptr;
2021 }
2022 else {
2023 raise_error = true;
2024 }
2025 }
2026 else {
2027 /* For function calls, we sometimes want to pass the 'ptr' directly,
2028 * but watch out that it remains valid!
2029 * We could possibly support this later if needed. */
2030 BLI_assert(value_new == nullptr);
2031 if (param == nullptr) {
2032 *((void **)data) = nullptr;
2033 }
2034 else if (RNA_struct_is_a(param->ptr->type, ptr_type)) {
2035 *((PointerRNA **)data) = &param->ptr.value();
2036 }
2037 else {
2038 raise_error = true;
2039 }
2040 }
2041 }
2042 else if (param == nullptr) {
2043 *((void **)data) = nullptr;
2044 }
2045 else if (RNA_struct_is_a(param->ptr->type, ptr_type)) {
2046 *((void **)data) = param->ptr->data;
2047 }
2048 else {
2049 raise_error = true;
2050 }
2051 }
2052 else {
2053 /* Data == nullptr, assign to RNA. */
2054 if ((param == nullptr) || RNA_struct_is_a(param->ptr->type, ptr_type)) {
2055 ReportList reports;
2058 ptr, prop, (param == nullptr) ? PointerRNA_NULL : *param->ptr, &reports);
2059 const int err = BPy_reports_to_error(&reports, PyExc_RuntimeError, true);
2060 if (err == -1) {
2061 Py_XDECREF(value_new);
2062 return -1;
2063 }
2064 }
2065 else {
2066 raise_error = true;
2067 }
2068 }
2069
2070 if (raise_error) {
2071 if (pyrna_struct_validity_check(param) == -1) {
2072 /* Error set. */
2073 }
2074 else {
2075 PointerRNA tmp = RNA_pointer_create_discrete(nullptr, ptr_type, nullptr);
2076 PyErr_Format(PyExc_TypeError,
2077 "%.200s %.200s.%.200s expected a %.200s type, not %.200s",
2078 error_prefix,
2082 RNA_struct_identifier(param->ptr->type));
2083 }
2084 Py_XDECREF(value_new);
2085 return -1;
2086 }
2087
2088 Py_XDECREF(value_new);
2089
2090 break;
2091 }
2092 case PROP_COLLECTION: {
2093 Py_ssize_t seq_len, i;
2094 PyObject *item;
2095 PointerRNA itemptr;
2096 CollectionVector *lb;
2097
2098 lb = (data) ? (CollectionVector *)data : nullptr;
2099
2100 /* Convert a sequence of dict's into a collection. */
2101 if (!PySequence_Check(value)) {
2102 PyErr_Format(
2103 PyExc_TypeError,
2104 "%.200s %.200s.%.200s expected a sequence for an RNA collection, not %.200s",
2105 error_prefix,
2108 Py_TYPE(value)->tp_name);
2109 return -1;
2110 }
2111
2112 seq_len = PySequence_Size(value);
2113 for (i = 0; i < seq_len; i++) {
2114 item = PySequence_GetItem(value, i);
2115
2116 if (item == nullptr) {
2117 PyErr_Format(
2118 PyExc_TypeError,
2119 "%.200s %.200s.%.200s failed to get sequence index '%d' for an RNA collection",
2120 error_prefix,
2123 i);
2124 Py_XDECREF(item);
2125 return -1;
2126 }
2127
2128 if (PyDict_Check(item) == 0) {
2129 PyErr_Format(PyExc_TypeError,
2130 "%.200s %.200s.%.200s expected a each sequence "
2131 "member to be a dict for an RNA collection, not %.200s",
2132 error_prefix,
2135 Py_TYPE(item)->tp_name);
2136 Py_XDECREF(item);
2137 return -1;
2138 }
2139
2140 if (lb) {
2141 lb->items.append(itemptr);
2142 }
2143 else {
2144 RNA_property_collection_add(ptr, prop, &itemptr);
2145 }
2146
2148 &itemptr, item, true, "Converting a Python list to an RNA collection") == -1)
2149 {
2150 PyObject *msg = PyC_ExceptionBuffer();
2151 const char *msg_char = PyUnicode_AsUTF8(msg);
2152 PyErr_Clear();
2153
2154 PyErr_Format(PyExc_TypeError,
2155 "%.200s %.200s.%.200s error converting a member of a collection "
2156 "from a dicts into an RNA collection, failed with: %s",
2157 error_prefix,
2160 msg_char);
2161
2162 Py_DECREF(item);
2163 Py_DECREF(msg);
2164 return -1;
2165 }
2166 Py_DECREF(item);
2167 }
2168
2169 break;
2170 }
2171 default:
2172 PyErr_Format(PyExc_AttributeError,
2173 "%.200s %.200s.%.200s unknown property type (pyrna_py_to_prop)",
2174 error_prefix,
2177 return -1;
2178 }
2179 }
2180
2181 /* Run RNA property functions. */
2182 if (RNA_property_update_check(prop)) {
2184 }
2185
2186 return 0;
2187}
2188
2190{
2192 return pyrna_py_from_array_index(self, &self->ptr.value(), self->prop, index);
2193}
2194
2195static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, PyObject *value)
2196{
2197 int ret = 0;
2198 PointerRNA *ptr = &self->ptr.value();
2199 PropertyRNA *prop = self->prop;
2200
2201 const int totdim = RNA_property_array_dimension(ptr, prop, nullptr);
2202
2203 if (totdim > 1) {
2204 // char error_str[512];
2206 &self->ptr.value(), self->prop, self->arraydim, self->arrayoffset, index, value, "") ==
2207 -1)
2208 {
2209 /* Error is set. */
2210 ret = -1;
2211 }
2212 }
2213 else {
2214 /* See if we can coerce into a Python type - 'PropertyType'. */
2215 switch (RNA_property_type(prop)) {
2216 case PROP_BOOLEAN: {
2217 const int param = PyC_Long_AsBool(value);
2218
2219 if (param == -1) {
2220 /* Error is set. */
2221 ret = -1;
2222 }
2223 else {
2224 RNA_property_boolean_set_index(ptr, prop, index, param);
2225 }
2226 break;
2227 }
2228 case PROP_INT: {
2229 int param = PyC_Long_AsI32(value);
2230 if (param == -1 && PyErr_Occurred()) {
2231 PyErr_SetString(PyExc_TypeError, "expected an int type");
2232 ret = -1;
2233 }
2234 else {
2235 RNA_property_int_clamp(ptr, prop, &param);
2236 RNA_property_int_set_index(ptr, prop, index, param);
2237 }
2238 break;
2239 }
2240 case PROP_FLOAT: {
2241 float param = PyFloat_AsDouble(value);
2242 if (PyErr_Occurred()) {
2243 PyErr_SetString(PyExc_TypeError, "expected a float type");
2244 ret = -1;
2245 }
2246 else {
2247 RNA_property_float_clamp(ptr, prop, &param);
2248 RNA_property_float_set_index(ptr, prop, index, param);
2249 }
2250 break;
2251 }
2252 default:
2253 PyErr_SetString(PyExc_AttributeError, "not an array type");
2254 ret = -1;
2255 break;
2256 }
2257 }
2258
2259 /* Run RNA property functions. */
2260 if (RNA_property_update_check(prop)) {
2262 }
2263
2264 return ret;
2265}
2266
2267/* ---------------sequence------------------------------------------- */
2269{
2271
2272 if (RNA_property_array_dimension(&self->ptr.value(), self->prop, nullptr) > 1) {
2273 return RNA_property_multi_array_length(&self->ptr.value(), self->prop, self->arraydim);
2274 }
2275
2276 return RNA_property_array_length(&self->ptr.value(), self->prop);
2277}
2278
2280{
2282
2283 return RNA_property_collection_length(&self->ptr.value(), self->prop);
2284}
2285
2286/* bool functions are for speed, so we can avoid getting the length
2287 * of 1000's of items in a linked list for eg. */
2289{
2291
2292 return RNA_property_array_length(&self->ptr.value(), self->prop) ? 1 : 0;
2293}
2294
2296{
2298
2299 return !RNA_property_collection_is_empty(&self->ptr.value(), self->prop);
2300}
2301
2302/* notice getting the length of the collection is avoided unless negative
2303 * index is used or to detect internal error with a valid index.
2304 * This is done for faster lookups. */
2305#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \
2306 if (keynum < 0) { \
2307 keynum_abs += RNA_property_collection_length(&self->ptr.value(), self->prop); \
2308 if (keynum_abs < 0) { \
2309 PyErr_Format(PyExc_IndexError, "bpy_prop_collection[%d]: out of range.", keynum); \
2310 return ret_err; \
2311 } \
2312 } \
2313 (void)0
2314
2319{
2320 if (value != Py_None) {
2322 const BPy_StructRNA *value_pyrna = (const BPy_StructRNA *)value;
2323 if (UNLIKELY(value_pyrna->ptr->type == nullptr)) {
2324 /* It's important to use a `TypeError` as that is what's returned when `__getitem__` is
2325 * called on an object that doesn't support item access. */
2326 PyErr_Format(PyExc_TypeError,
2327 "'%.200s' object is not subscriptable (only iteration is supported)",
2328 Py_TYPE(value)->tp_name);
2329 return -1;
2330 }
2331 }
2332 return 0;
2333}
2334
2336 const char *error_prefix)
2337{
2338 PyErr_Format(PyExc_TypeError,
2339 "%.200s: %.200s.%.200s does not support string lookups",
2340 error_prefix,
2341 RNA_struct_identifier(self->ptr->type),
2343}
2344
2346 const char *error_prefix)
2347{
2350 return 0;
2351 }
2353 return -1;
2354}
2355
2356/* Internal use only. */
2357static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum)
2358{
2359 PointerRNA newptr;
2360 Py_ssize_t keynum_abs = keynum;
2361
2363
2365
2367 if (RNA_property_collection_lookup_int(&self->ptr.value(), self->prop, keynum_abs, &newptr)) {
2368 return pyrna_struct_CreatePyObject(&newptr);
2369 }
2370 }
2371 else {
2372 /* No callback defined, just iterate and find the nth item. */
2373 const int key = int(keynum_abs);
2374 PyObject *result = nullptr;
2375 bool found = false;
2377 RNA_property_collection_begin(&self->ptr.value(), self->prop, &iter);
2378 for (int i = 0; iter.valid; RNA_property_collection_next(&iter), i++) {
2379 if (i == key) {
2381 found = true;
2382 break;
2383 }
2384 }
2385 /* It's important to end the iterator after `result` has been created
2386 * so iterators may optionally invalidate items that were iterated over, see: #100286. */
2388 if (found) {
2391 result = nullptr; /* The exception has been set. */
2392 }
2393 return result;
2394 }
2395 }
2396
2397 const int len = RNA_property_collection_length(&self->ptr.value(), self->prop);
2398 if (keynum_abs >= len) {
2399 PyErr_Format(PyExc_IndexError,
2400 "bpy_prop_collection[index]: "
2401 "index %d out of range, size %d",
2402 keynum,
2403 len);
2404 }
2405 else {
2406 PyErr_Format(PyExc_RuntimeError,
2407 "bpy_prop_collection[index]: internal error, "
2408 "valid index %d given in %d sized collection, but value not found",
2409 keynum_abs,
2410 len);
2411 }
2412
2413 return nullptr;
2414}
2415
2416/* Values type must have been already checked. */
2418 Py_ssize_t keynum,
2419 PyObject *value)
2420{
2421 Py_ssize_t keynum_abs = keynum;
2422 const PointerRNA *ptr = (value == Py_None) ?
2423 (&PointerRNA_NULL) :
2424 &(reinterpret_cast<BPy_StructRNA *>(value))->ptr.value();
2425
2427
2429
2430 if (!RNA_property_collection_assign_int(&self->ptr.value(), self->prop, keynum_abs, ptr)) {
2431 const int len = RNA_property_collection_length(&self->ptr.value(), self->prop);
2432 if (keynum_abs >= len) {
2433 PyErr_Format(PyExc_IndexError,
2434 "bpy_prop_collection[index] = value: "
2435 "index %d out of range, size %d",
2436 keynum,
2437 len);
2438 }
2439 else {
2440 PyErr_Format(PyExc_IndexError,
2441 "bpy_prop_collection[index] = value: "
2442 "index %d failed assignment (unknown reason)",
2443 keynum);
2444 }
2445 return -1;
2446 }
2447
2448 return 0;
2449}
2450
2451static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, Py_ssize_t keynum)
2452{
2453 int len;
2454
2456
2458
2459 if (keynum < 0) {
2460 keynum += len;
2461 }
2462
2463 if (keynum >= 0 && keynum < len) {
2464 return pyrna_prop_array_to_py_index(self, keynum);
2465 }
2466
2467 PyErr_Format(PyExc_IndexError, "bpy_prop_array[index]: index %d out of range", keynum);
2468 return nullptr;
2469}
2470
2471static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, const char *keyname)
2472{
2473 PointerRNA newptr;
2474
2476
2478 if (RNA_property_collection_lookup_string(&self->ptr.value(), self->prop, keyname, &newptr)) {
2479 return pyrna_struct_CreatePyObject(&newptr);
2480 }
2481 }
2483 /* No callback defined, just iterate and find the nth item. */
2484 const int key_len = strlen(keyname);
2485 char name[256];
2486 int name_len;
2487 PyObject *result = nullptr;
2488 bool found = false;
2490 RNA_property_collection_begin(&self->ptr.value(), self->prop, &iter);
2491 for (; iter.valid; RNA_property_collection_next(&iter)) {
2492 PropertyRNA *nameprop = RNA_struct_name_property(iter.ptr.type);
2493 /* The #RNA_property_collection_lookup_string_has_nameprop check should account for this.
2494 * Although it's technically possible a sub-type clears the name property,
2495 * this seems unlikely. */
2496 BLI_assert(nameprop != nullptr);
2497 char *name_ptr = RNA_property_string_get_alloc(
2498 &iter.ptr, nameprop, name, sizeof(name), &name_len);
2499 if ((key_len == name_len) && STREQ(name_ptr, keyname)) {
2500 found = true;
2501 }
2502 if (name != name_ptr) {
2503 MEM_freeN(name_ptr);
2504 }
2505 if (found) {
2507 break;
2508 }
2509 }
2510 /* It's important to end the iterator after `result` has been created
2511 * so iterators may optionally invalidate items that were iterated over, see: #100286. */
2513 if (found) {
2516 result = nullptr; /* The exception has been set. */
2517 }
2518 return result;
2519 }
2520 }
2521 else {
2523 return nullptr;
2524 }
2525
2526 PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname);
2527 return nullptr;
2528}
2529// static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname)
2530
2543 PyObject *key,
2544 const char *err_prefix,
2545 const short err_not_found,
2546 PointerRNA *r_ptr)
2547{
2548 const char *keyname;
2549
2550 /* First validate the args, all we know is that they are a tuple. */
2551 if (PyTuple_GET_SIZE(key) != 2) {
2552 PyErr_Format(PyExc_KeyError,
2553 "%s: tuple key must be a pair, not size %d",
2554 err_prefix,
2555 PyTuple_GET_SIZE(key));
2556 return -1;
2557 }
2558 if (self->ptr->type != &RNA_BlendData) {
2559 PyErr_Format(PyExc_KeyError,
2560 "%s: is only valid for bpy.data collections, not %.200s",
2561 err_prefix,
2562 RNA_struct_identifier(self->ptr->type));
2563 return -1;
2564 }
2565 if ((keyname = PyUnicode_AsUTF8(PyTuple_GET_ITEM(key, 0))) == nullptr) {
2566 PyErr_Format(PyExc_KeyError,
2567 "%s: id must be a string, not %.200s",
2568 err_prefix,
2569 Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name);
2570 return -1;
2571 }
2572
2573 PyObject *keylib = PyTuple_GET_ITEM(key, 1);
2574 Library *lib;
2575 bool found = false;
2576
2577 if (keylib == Py_None) {
2578 lib = nullptr;
2579 }
2580 else if (PyUnicode_Check(keylib)) {
2581 Main *bmain = static_cast<Main *>(self->ptr->data);
2582 const char *keylib_str = PyUnicode_AsUTF8(keylib);
2583 lib = static_cast<Library *>(
2584 BLI_findstring(&bmain->libraries, keylib_str, offsetof(Library, filepath)));
2585 if (lib == nullptr) {
2586 if (err_not_found) {
2587 PyErr_Format(PyExc_KeyError,
2588 "%s: lib filepath '%.1024s' "
2589 "does not reference a valid library",
2590 err_prefix,
2591 keylib_str);
2592 return -1;
2593 }
2594
2595 return 0;
2596 }
2597 }
2598 else {
2599 PyErr_Format(PyExc_KeyError,
2600 "%s: lib must be a string or None, not %.200s",
2601 err_prefix,
2602 Py_TYPE(keylib)->tp_name);
2603 return -1;
2604 }
2605
2606 /* lib is either a valid pointer or nullptr,
2607 * either way can do direct comparison with id.lib */
2608
2609 RNA_PROP_BEGIN (&self->ptr.value(), itemptr, self->prop) {
2610 ID *id = static_cast<ID *>(itemptr.data); /* Always an ID. */
2611 if (id->lib == lib && STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2)) {
2612 found = true;
2613 if (r_ptr) {
2614 *r_ptr = itemptr;
2615 }
2616 break;
2617 }
2618 }
2620
2621 /* We may want to fail silently as with collection.get(). */
2622 if ((found == false) && err_not_found) {
2623 /* Only runs for getitem access so use fixed string. */
2624 PyErr_SetString(PyExc_KeyError, "bpy_prop_collection[key, lib]: not found");
2625 return -1;
2626 }
2627
2628 return found; /* 1 / 0, no exception. */
2629}
2630
2632 PyObject *key,
2633 const char *err_prefix,
2634 const bool err_not_found)
2635{
2638 self, key, err_prefix, err_not_found, &ptr);
2639
2640 if (contains == 1) {
2642 }
2643
2644 return nullptr;
2645}
2646
2648 Py_ssize_t start,
2649 Py_ssize_t stop)
2650{
2651 CollectionPropertyIterator rna_macro_iter;
2652 int count;
2653
2654 PyObject *list;
2655 PyObject *item;
2656
2658
2659 list = PyList_New(0);
2660
2661 /* Skip to start. */
2662 RNA_property_collection_begin(&self->ptr.value(), self->prop, &rna_macro_iter);
2663 RNA_property_collection_skip(&rna_macro_iter, start);
2664
2665 /* Add items until stop. */
2666 for (count = start; rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) {
2667 item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr);
2668 PyList_APPEND(list, item);
2669
2670 count++;
2671 if (count == stop) {
2672 break;
2673 }
2674 }
2675
2676 RNA_property_collection_end(&rna_macro_iter);
2677
2678 return list;
2679}
2680
2687 PointerRNA *ptr,
2688 PropertyRNA *prop,
2689 Py_ssize_t start,
2690 Py_ssize_t stop,
2691 Py_ssize_t length)
2692{
2693 int count, totdim;
2694 PyObject *tuple;
2695
2696 /* Isn't needed, internal use only. */
2697 // PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self);
2698
2699 tuple = PyTuple_New(stop - start);
2700
2701 totdim = RNA_property_array_dimension(ptr, prop, nullptr);
2702
2703 if (totdim > 1) {
2704 for (count = start; count < stop; count++) {
2705 PyTuple_SET_ITEM(tuple, count - start, pyrna_prop_array_to_py_index(self, count));
2706 }
2707 }
2708 else {
2709 switch (RNA_property_type(prop)) {
2710 case PROP_FLOAT: {
2711 float values_stack[PYRNA_STACK_ARRAY];
2712 float *values;
2713 if (length > PYRNA_STACK_ARRAY) {
2714 values = static_cast<float *>(PyMem_MALLOC(sizeof(float) * length));
2715 }
2716 else {
2717 values = values_stack;
2718 }
2719 RNA_property_float_get_array(ptr, prop, values);
2720
2721 for (count = start; count < stop; count++) {
2722 PyTuple_SET_ITEM(tuple, count - start, PyFloat_FromDouble(values[count]));
2723 }
2724
2725 if (values != values_stack) {
2726 PyMem_FREE(values);
2727 }
2728 break;
2729 }
2730 case PROP_BOOLEAN: {
2731 bool values_stack[PYRNA_STACK_ARRAY];
2732 bool *values;
2733 if (length > PYRNA_STACK_ARRAY) {
2734 values = static_cast<bool *>(PyMem_MALLOC(sizeof(bool) * length));
2735 }
2736 else {
2737 values = values_stack;
2738 }
2739
2740 RNA_property_boolean_get_array(ptr, prop, values);
2741 for (count = start; count < stop; count++) {
2742 PyTuple_SET_ITEM(tuple, count - start, PyBool_FromLong(values[count]));
2743 }
2744
2745 if (values != values_stack) {
2746 PyMem_FREE(values);
2747 }
2748 break;
2749 }
2750 case PROP_INT: {
2751 int values_stack[PYRNA_STACK_ARRAY];
2752 int *values;
2753 if (length > PYRNA_STACK_ARRAY) {
2754 values = static_cast<int *>(PyMem_MALLOC(sizeof(int) * length));
2755 }
2756 else {
2757 values = values_stack;
2758 }
2759
2760 RNA_property_int_get_array(ptr, prop, values);
2761 for (count = start; count < stop; count++) {
2762 PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count]));
2763 }
2764
2765 if (values != values_stack) {
2766 PyMem_FREE(values);
2767 }
2768 break;
2769 }
2770 default:
2771 BLI_assert_msg(0, "Invalid array type");
2772
2773 PyErr_SetString(PyExc_TypeError, "not an array type");
2774 Py_DECREF(tuple);
2775 tuple = nullptr;
2776 break;
2777 }
2778 }
2779 return tuple;
2780}
2781
2783{
2785
2786 if (PyUnicode_Check(key)) {
2787 return pyrna_prop_collection_subscript_str(self, PyUnicode_AsUTF8(key));
2788 }
2789 if (PyIndex_Check(key)) {
2790 const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2791 if (i == -1 && PyErr_Occurred()) {
2792 return nullptr;
2793 }
2794
2796 }
2797 if (PySlice_Check(key)) {
2798 PySliceObject *key_slice = (PySliceObject *)key;
2799 Py_ssize_t step = 1;
2800
2801 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2802 return nullptr;
2803 }
2804 if (step != 1) {
2805 PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported");
2806 return nullptr;
2807 }
2808 if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2809 return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
2810 }
2811
2812 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
2813
2814 /* Avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
2815 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
2816 return nullptr;
2817 }
2818 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
2819 return nullptr;
2820 }
2821
2822 if (start < 0 || stop < 0) {
2823 /* Only get the length for negative values. */
2824 const Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr.value(),
2825 self->prop);
2826 if (start < 0) {
2827 start += len;
2828 CLAMP_MIN(start, 0);
2829 }
2830 if (stop < 0) {
2831 stop += len;
2832 CLAMP_MIN(stop, 0);
2833 }
2834 }
2835
2836 if (stop - start <= 0) {
2837 return PyList_New(0);
2838 }
2839
2840 return pyrna_prop_collection_subscript_slice(self, start, stop);
2841 }
2842 if (PyTuple_Check(key)) {
2843 /* Special case, for ID data-blocks. */
2845 self, key, "bpy_prop_collection[id, lib]", true);
2846 }
2847
2848 PyErr_Format(PyExc_TypeError,
2849 "bpy_prop_collection[key]: invalid key, "
2850 "must be a string or an int, not %.200s",
2851 Py_TYPE(key)->tp_name);
2852 return nullptr;
2853}
2854
2855/* generic check to see if a PyObject is compatible with a collection
2856 * -1 on failure, 0 on success, sets the error */
2858{
2859 StructRNA *prop_srna;
2860
2861 if (value == Py_None) {
2862 if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) {
2863 PyErr_SetString(PyExc_TypeError,
2864 "bpy_prop_collection[key] = value: invalid, "
2865 "this collection doesn't support None assignment");
2866 return -1;
2867 }
2868
2869 return 0; /* None is OK. */
2870 }
2871 if (BPy_StructRNA_Check(value) == 0) {
2872 PyErr_Format(PyExc_TypeError,
2873 "bpy_prop_collection[key] = value: invalid, "
2874 "expected a StructRNA type or None, not a %.200s",
2875 Py_TYPE(value)->tp_name);
2876 return -1;
2877 }
2878 if ((prop_srna = RNA_property_pointer_type(&self->ptr.value(), self->prop))) {
2879 StructRNA *value_srna = ((BPy_StructRNA *)value)->ptr->type;
2880 if (RNA_struct_is_a(value_srna, prop_srna) == 0) {
2881 PyErr_Format(PyExc_TypeError,
2882 "bpy_prop_collection[key] = value: invalid, "
2883 "expected a '%.200s' type or None, not a '%.200s'",
2884 RNA_struct_identifier(prop_srna),
2885 RNA_struct_identifier(value_srna));
2886 return -1;
2887 }
2888
2889 return 0; /* OK, this is the correct type! */
2890 }
2891
2892 PyErr_SetString(PyExc_TypeError,
2893 "bpy_prop_collection[key] = value: internal error, "
2894 "failed to get the collection type");
2895 return -1;
2896}
2897
2898/* NOTE: currently this is a copy of 'pyrna_prop_collection_subscript' with
2899 * large blocks commented, we may support slice/key indices later */
2901 PyObject *key,
2902 PyObject *value)
2903{
2905
2906 /* Validate the assigned value. */
2907 if (value == nullptr) {
2908 PyErr_SetString(PyExc_TypeError, "del bpy_prop_collection[key]: not supported");
2909 return -1;
2910 }
2911 if (pyrna_prop_collection_type_check(self, value) == -1) {
2912 return -1; /* Exception is set. */
2913 }
2914
2915#if 0
2916 if (PyUnicode_Check(key)) {
2917 return pyrna_prop_collection_subscript_str(self, PyUnicode_AsUTF8(key));
2918 }
2919 else
2920#endif
2921 if (PyIndex_Check(key)) {
2922 const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2923 if (i == -1 && PyErr_Occurred()) {
2924 return -1;
2925 }
2926
2928 }
2929#if 0 /* TODO: fake slice assignment. */
2930 else if (PySlice_Check(key)) {
2931 PySliceObject *key_slice = (PySliceObject *)key;
2932 Py_ssize_t step = 1;
2933
2934 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2935 return nullptr;
2936 }
2937 else if (step != 1) {
2938 PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported");
2939 return nullptr;
2940 }
2941 else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2942 return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
2943 }
2944 else {
2945 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
2946
2947 /* Avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
2948 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
2949 return nullptr;
2950 }
2951 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
2952 return nullptr;
2953 }
2954
2955 if (start < 0 || stop < 0) {
2956 /* Only get the length for negative values. */
2957 Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr.value(), self->prop);
2958 if (start < 0) {
2959 start += len;
2960 CLAMP_MIN(start, 0);
2961 }
2962 if (stop < 0) {
2963 stop += len;
2964 CLAMP_MIN(stop, 0);
2965 }
2966 }
2967
2968 if (stop - start <= 0) {
2969 return PyList_New(0);
2970 }
2971 else {
2972 return pyrna_prop_collection_subscript_slice(self, start, stop);
2973 }
2974 }
2975 }
2976#endif
2977
2978 PyErr_Format(PyExc_TypeError,
2979 "bpy_prop_collection[key]: invalid key, "
2980 "must be an int, not %.200s",
2981 Py_TYPE(key)->tp_name);
2982 return -1;
2983}
2984
2986{
2988
2989#if 0
2990 if (PyUnicode_Check(key)) {
2991 return pyrna_prop_array_subscript_str(self, PyUnicode_AsUTF8(key));
2992 }
2993 else
2994#endif
2995 if (PyIndex_Check(key)) {
2996 const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2997 if (i == -1 && PyErr_Occurred()) {
2998 return nullptr;
2999 }
3001 }
3002 if (PySlice_Check(key)) {
3003 Py_ssize_t step = 1;
3004 PySliceObject *key_slice = (PySliceObject *)key;
3005
3006 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
3007 return nullptr;
3008 }
3009 if (step != 1) {
3010 PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported");
3011 return nullptr;
3012 }
3013 if (key_slice->start == Py_None && key_slice->stop == Py_None) {
3014 /* NOTE: no significant advantage with optimizing [:] slice as with collections,
3015 * but include here for consistency with collection slice func */
3016 const Py_ssize_t len = pyrna_prop_array_length(self);
3017 return pyrna_prop_array_subscript_slice(self, &self->ptr.value(), self->prop, 0, len, len);
3018 }
3019
3020 const int len = pyrna_prop_array_length(self);
3021 Py_ssize_t start, stop, slicelength;
3022
3023 if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) {
3024 return nullptr;
3025 }
3026
3027 if (slicelength <= 0) {
3028 return PyTuple_New(0);
3029 }
3030
3032 self, &self->ptr.value(), self->prop, start, stop, len);
3033 }
3034
3035 PyErr_SetString(PyExc_AttributeError, "bpy_prop_array[key]: invalid key, key must be an int");
3036 return nullptr;
3037}
3038
3042
3043static PyObject *prop_subscript_ass_array_slice__as_seq_fast(PyObject *value, int length)
3044{
3045 PyObject *value_fast;
3046 if (!(value_fast = PySequence_Fast(value,
3047 "bpy_prop_array[slice] = value: "
3048 "element in assignment is not a sequence type")))
3049 {
3050 return nullptr;
3051 }
3052 if (PySequence_Fast_GET_SIZE(value_fast) != length) {
3053 Py_DECREF(value_fast);
3054 PyErr_SetString(PyExc_ValueError,
3055 "bpy_prop_array[slice] = value: "
3056 "re-sizing bpy_struct element in arrays isn't supported");
3057 return nullptr;
3058 }
3059
3060 return value_fast;
3061}
3062
3064 PyObject **value_items, float *value, int totdim, const int dimsize[], const float range[2])
3065{
3066 const int length = dimsize[0];
3067 if (totdim > 1) {
3068 int index = 0;
3069 int i;
3070 for (i = 0; i != length; i++) {
3071 PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]);
3072 if (UNLIKELY(subvalue == nullptr)) {
3073 return 0;
3074 }
3075
3077 PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range);
3078
3079 Py_DECREF(subvalue);
3080 }
3081 return index;
3082 }
3083
3084 BLI_assert(totdim == 1);
3085 const float min = range[0], max = range[1];
3086 int i;
3087 for (i = 0; i != length; i++) {
3088 float v = PyFloat_AsDouble(value_items[i]);
3089 CLAMP(v, min, max);
3090 value[i] = v;
3091 }
3092 return i;
3093}
3094
3096 PyObject **value_items, int *value, int totdim, const int dimsize[], const int range[2])
3097{
3098 const int length = dimsize[0];
3099 if (totdim > 1) {
3100 int index = 0;
3101 int i;
3102 for (i = 0; i != length; i++) {
3103 PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]);
3104 if (UNLIKELY(subvalue == nullptr)) {
3105 return 0;
3106 }
3107
3109 PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range);
3110
3111 Py_DECREF(subvalue);
3112 }
3113 return index;
3114 }
3115
3116 BLI_assert(totdim == 1);
3117 const int min = range[0], max = range[1];
3118 int i;
3119 for (i = 0; i != length; i++) {
3120 int v = PyLong_AsLong(value_items[i]);
3121 CLAMP(v, min, max);
3122 value[i] = v;
3123 }
3124 return i;
3125}
3126
3127static int prop_subscript_ass_array_slice__bool_recursive(PyObject **value_items,
3128 bool *value,
3129 int totdim,
3130 const int dimsize[])
3131{
3132 const int length = dimsize[0];
3133 if (totdim > 1) {
3134 int index = 0;
3135 int i;
3136 for (i = 0; i != length; i++) {
3137 PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]);
3138 if (UNLIKELY(subvalue == nullptr)) {
3139 return 0;
3140 }
3141
3143 PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1]);
3144
3145 Py_DECREF(subvalue);
3146 }
3147 return index;
3148 }
3149
3150 BLI_assert(totdim == 1);
3151 int i;
3152 for (i = 0; i != length; i++) {
3153 const int v = PyLong_AsLong(value_items[i]);
3154 value[i] = v;
3155 }
3156 return i;
3157}
3158
3159/* Could call `pyrna_py_to_prop_array_index(self, i, value)` in a loop, but it is slow. */
3161 PropertyRNA *prop,
3162 int arraydim,
3163 int arrayoffset,
3164 int start,
3165 int stop,
3166 int length,
3167 PyObject *value_orig)
3168{
3169 const int length_flat = RNA_property_array_length(ptr, prop);
3170 PyObject *value;
3171 void *values_alloc = nullptr;
3172 int ret = 0;
3173
3174 if (value_orig == nullptr) {
3175 PyErr_SetString(
3176 PyExc_TypeError,
3177 "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct");
3178 return -1;
3179 }
3180
3181 if (!(value = PySequence_Fast(
3182 value_orig, "bpy_prop_array[slice] = value: assignment is not a sequence type")))
3183 {
3184 return -1;
3185 }
3186
3187 if (PySequence_Fast_GET_SIZE(value) != stop - start) {
3188 Py_DECREF(value);
3189 PyErr_SetString(PyExc_TypeError,
3190 "bpy_prop_array[slice] = value: re-sizing bpy_struct arrays isn't supported");
3191 return -1;
3192 }
3193
3194 int dimsize[3];
3195 const int totdim = RNA_property_array_dimension(ptr, prop, dimsize);
3196 if (totdim > 1) {
3197 BLI_assert(dimsize[arraydim] == length);
3198 }
3199
3200 int span = 1;
3201 if (totdim > 1) {
3202 for (int i = arraydim + 1; i < totdim; i++) {
3203 span *= dimsize[i];
3204 }
3205 }
3206
3207 /* Assigning as subset of the whole array.
3208 *
3209 * When false, the whole array is being assigned, otherwise the array be read into `values`,
3210 * the subset updated & the whole array written back (since RNA doesn't support sub-ranges). */
3211 const bool is_subset = start != 0 || stop != length || arrayoffset != 0 || arraydim != 0;
3212
3213 PyObject **value_items = PySequence_Fast_ITEMS(value);
3214 switch (RNA_property_type(prop)) {
3215 case PROP_FLOAT: {
3216 float values_stack[PYRNA_STACK_ARRAY];
3217 float *values = static_cast<float *>(
3218 (length_flat > PYRNA_STACK_ARRAY) ?
3219 (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) :
3220 values_stack);
3221 if (is_subset) {
3222 RNA_property_float_get_array(ptr, prop, values);
3223 }
3224
3225 float range[2];
3226 RNA_property_float_range(ptr, prop, &range[0], &range[1]);
3227
3228 dimsize[arraydim] = stop - start;
3230 &values[arrayoffset + (start * span)],
3231 totdim - arraydim,
3232 &dimsize[arraydim],
3233 range);
3234
3235 if (PyErr_Occurred()) {
3236 ret = -1;
3237 }
3238 else {
3239 RNA_property_float_set_array(ptr, prop, values);
3240 }
3241 break;
3242 }
3243 case PROP_INT: {
3244 int values_stack[PYRNA_STACK_ARRAY];
3245 int *values = static_cast<int *>(
3246 (length_flat > PYRNA_STACK_ARRAY) ?
3247 (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) :
3248 values_stack);
3249 if (is_subset) {
3250 RNA_property_int_get_array(ptr, prop, values);
3251 }
3252
3253 int range[2];
3254 RNA_property_int_range(ptr, prop, &range[0], &range[1]);
3255
3256 dimsize[arraydim] = stop - start;
3258 &values[arrayoffset + (start * span)],
3259 totdim - arraydim,
3260 &dimsize[arraydim],
3261 range);
3262
3263 if (PyErr_Occurred()) {
3264 ret = -1;
3265 }
3266 else {
3267 RNA_property_int_set_array(ptr, prop, values);
3268 }
3269 break;
3270 }
3271 case PROP_BOOLEAN: {
3272 bool values_stack[PYRNA_STACK_ARRAY];
3273 bool *values = static_cast<bool *>(
3274 (length_flat > PYRNA_STACK_ARRAY) ?
3275 (values_alloc = PyMem_MALLOC(sizeof(bool) * length_flat)) :
3276 values_stack);
3277
3278 if (is_subset) {
3279 RNA_property_boolean_get_array(ptr, prop, values);
3280 }
3281
3282 dimsize[arraydim] = stop - start;
3284 &values[arrayoffset + (start * span)],
3285 totdim - arraydim,
3286 &dimsize[arraydim]);
3287
3288 if (PyErr_Occurred()) {
3289 ret = -1;
3290 }
3291 else {
3292 RNA_property_boolean_set_array(ptr, prop, values);
3293 }
3294 break;
3295 }
3296 default:
3297 PyErr_SetString(PyExc_TypeError, "not an array type");
3298 ret = -1;
3299 break;
3300 }
3301
3302 Py_DECREF(value);
3303
3304 if (values_alloc) {
3305 PyMem_FREE(values_alloc);
3306 }
3307
3308 return ret;
3309}
3310
3312 Py_ssize_t keynum,
3313 PyObject *value)
3314{
3316
3318
3319 if (keynum < 0) {
3320 keynum += len;
3321 }
3322
3323 if (keynum >= 0 && keynum < len) {
3324 return pyrna_py_to_prop_array_index(self, keynum, value);
3325 }
3326
3327 PyErr_SetString(PyExc_IndexError, "bpy_prop_array[index] = value: index out of range");
3328 return -1;
3329}
3330
3332 PyObject *key,
3333 PyObject *value)
3334{
3335 // char *keyname = nullptr; /* Not supported yet. */
3336 int ret = -1;
3337
3339
3340 if (!RNA_property_editable_flag(&self->ptr.value(), self->prop)) {
3341 PyErr_Format(PyExc_AttributeError,
3342 "bpy_prop_collection: attribute \"%.200s\" from \"%.200s\" is read-only",
3344 RNA_struct_identifier(self->ptr->type));
3345 ret = -1;
3346 }
3347
3348 else if (PyIndex_Check(key)) {
3349 const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
3350 if (i == -1 && PyErr_Occurred()) {
3351 ret = -1;
3352 }
3353 else {
3355 }
3356 }
3357 else if (PySlice_Check(key)) {
3358 const Py_ssize_t len = pyrna_prop_array_length(self);
3359 Py_ssize_t start, stop, step, slicelength;
3360
3361 if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) {
3362 ret = -1;
3363 }
3364 else if (slicelength <= 0) {
3365 ret = 0; /* Do nothing. */
3366 }
3367 else if (step == 1) {
3368 ret = prop_subscript_ass_array_slice(&self->ptr.value(),
3369 self->prop,
3370 self->arraydim,
3371 self->arrayoffset,
3372 start,
3373 stop,
3374 len,
3375 value);
3376 }
3377 else {
3378 PyErr_SetString(PyExc_TypeError, "slice steps not supported with RNA");
3379 ret = -1;
3380 }
3381 }
3382 else {
3383 PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int");
3384 ret = -1;
3385 }
3386
3387 if (ret != -1) {
3388 if (RNA_property_update_check(self->prop)) {
3389 RNA_property_update(BPY_context_get(), &self->ptr.value(), self->prop);
3390 }
3391 }
3392
3393 return ret;
3394}
3395
3396/* For slice only. */
3397static PyMappingMethods pyrna_prop_array_as_mapping = {
3398 /*mp_length*/ (lenfunc)pyrna_prop_array_length,
3399 /*mp_subscript*/ (binaryfunc)pyrna_prop_array_subscript,
3400 /*mp_ass_subscript*/ (objobjargproc)pyrna_prop_array_ass_subscript,
3401};
3402
3403static PyMappingMethods pyrna_prop_collection_as_mapping = {
3404 /*mp_length*/ (lenfunc)pyrna_prop_collection_length,
3405 /*mp_subscript*/ (binaryfunc)pyrna_prop_collection_subscript,
3406 /*mp_ass_subscript*/ (objobjargproc)pyrna_prop_collection_ass_subscript,
3407};
3408
3409/* Only for fast bool's, large structs, assign nb_bool on init. */
3410static PyNumberMethods pyrna_prop_array_as_number = {
3411 /*nb_add*/ nullptr,
3412 /*nb_subtract*/ nullptr,
3413 /*nb_multiply*/ nullptr,
3414 /*nb_remainder*/ nullptr,
3415 /*nb_divmod*/ nullptr,
3416 /*nb_power*/ nullptr,
3417 /*nb_negative*/ nullptr,
3418 /*nb_positive*/ nullptr,
3419 /*nb_absolute*/ nullptr,
3420 /*nb_bool*/ (inquiry)pyrna_prop_array_bool,
3421};
3422static PyNumberMethods pyrna_prop_collection_as_number = {
3423 /*nb_add*/ nullptr,
3424 /*nb_subtract*/ nullptr,
3425 /*nb_multiply*/ nullptr,
3426 /*nb_remainder*/ nullptr,
3427 /*nb_divmod*/ nullptr,
3428 /*nb_power*/ nullptr,
3429 /*nb_negative*/ nullptr,
3430 /*nb_positive*/ nullptr,
3431 /*nb_absolute*/ nullptr,
3432 /*nb_bool*/ (inquiry)pyrna_prop_collection_bool,
3433 /*nb_invert*/ nullptr,
3434 /*nb_lshift*/ nullptr,
3435 /*nb_rshift*/ nullptr,
3436 /*nb_and*/ nullptr,
3437 /*nb_xor*/ nullptr,
3438 /*nb_or*/ nullptr,
3439 /*nb_int*/ nullptr,
3440 /*nb_reserved*/ nullptr,
3441 /*nb_float*/ nullptr,
3442 /*nb_inplace_add*/ nullptr,
3443 /*nb_inplace_subtract*/ nullptr,
3444 /*nb_inplace_multiply*/ nullptr,
3445 /*nb_inplace_remainder*/ nullptr,
3446 /*nb_inplace_power*/ nullptr,
3447 /*nb_inplace_lshift*/ nullptr,
3448 /*nb_inplace_rshift*/ nullptr,
3449 /*nb_inplace_and*/ nullptr,
3450 /*nb_inplace_xor*/ nullptr,
3451 /*nb_inplace_or*/ nullptr,
3452 /*nb_floor_divide*/ nullptr,
3453 /*nb_true_divide*/ nullptr,
3454 /*nb_inplace_floor_divide*/ nullptr,
3455 /*nb_inplace_true_divide*/ nullptr,
3456 /*nb_index*/ nullptr,
3457 /*nb_matrix_multiply*/ nullptr,
3458 /*nb_inplace_matrix_multiply*/ nullptr,
3459};
3460
3462{
3463 return pyrna_array_contains_py(&self->ptr.value(), self->prop, value);
3464}
3465
3467{
3468 PointerRNA newptr; /* Not used, just so RNA_property_collection_lookup_string runs. */
3469
3470 if (PyTuple_Check(key)) {
3471 /* Special case, for ID data-blocks. */
3473 self, key, "(id, lib) in bpy_prop_collection", false, nullptr);
3474 }
3475
3476 /* Key in dict style check. */
3477 const char *keyname = PyUnicode_AsUTF8(key);
3478
3479 if (keyname == nullptr) {
3480 PyErr_SetString(PyExc_TypeError,
3481 "bpy_prop_collection.__contains__: expected a string or a tuple of strings");
3482 return -1;
3483 }
3484
3485 if (RNA_property_collection_lookup_string(&self->ptr.value(), self->prop, keyname, &newptr)) {
3486 return 1;
3487 }
3489 self, "bpy_prop_collection.__contains__") == -1)
3490 {
3491 return -1;
3492 }
3493
3494 return 0;
3495}
3496
3497static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value)
3498{
3499 const char *name = PyUnicode_AsUTF8(value);
3500
3502
3503 if (!name) {
3504 PyErr_SetString(PyExc_TypeError, "bpy_struct.__contains__: expected a string");
3505 return -1;
3506 }
3507
3508 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
3509 PyErr_SetString(PyExc_TypeError, "bpy_struct: this type doesn't support IDProperties");
3510 return -1;
3511 }
3512
3513 IDProperty *group = RNA_struct_idprops(&self->ptr.value(), false);
3514
3515 if (!group) {
3516 return 0;
3517 }
3518
3519 return IDP_GetPropertyFromGroup(group, name) ? 1 : 0;
3520}
3521
3522static PySequenceMethods pyrna_prop_array_as_sequence = {
3523 /*sq_length*/ (lenfunc)pyrna_prop_array_length,
3524 /*sq_concat*/ nullptr,
3525 /*sq_repeat*/ nullptr,
3526 /* Only set this so `PySequence_Check()` returns True. */
3527 /*sq_item*/ (ssizeargfunc)pyrna_prop_array_subscript_int,
3528 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
3529 /*sq_ass_item*/ (ssizeobjargproc)prop_subscript_ass_array_int,
3530 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
3531 /*sq_contains*/ (objobjproc)pyrna_prop_array_contains,
3532 /*sq_inplace_concat*/ nullptr,
3533 /*sq_inplace_repeat*/ nullptr,
3534};
3535
3536static PySequenceMethods pyrna_prop_collection_as_sequence = {
3537 /*sq_length*/ (lenfunc)pyrna_prop_collection_length,
3538 /*sq_concat*/ nullptr,
3539 /*sq_repeat*/ nullptr,
3540 /* Only set this so PySequence_Check() returns True */
3541 /*sq_item*/ (ssizeargfunc)pyrna_prop_collection_subscript_int,
3542 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
3543 /* Let mapping take this one: #pyrna_prop_collection_ass_subscript_int */
3544 /*sq_ass_item*/ nullptr,
3545 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
3546 /*sq_contains*/ (objobjproc)pyrna_prop_collection_contains,
3547 /*sq_inplace_concat*/ nullptr,
3548 /*sq_inplace_repeat*/ nullptr,
3549};
3550
3551static PySequenceMethods pyrna_struct_as_sequence = {
3552 /*sq_length*/ nullptr, /* Can't set the len otherwise it can evaluate as false */
3553 /*sq_concat*/ nullptr,
3554 /*sq_repeat*/ nullptr,
3555 /* Only set this so `PySequence_Check()` returns True. */
3556 /*sq_item*/ nullptr,
3557 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
3558 /*sq_ass_item*/ nullptr,
3559 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
3560 /*sq_contains*/ (objobjproc)pyrna_struct_contains,
3561 /*sq_inplace_concat*/ nullptr,
3562 /*sq_inplace_repeat*/ nullptr,
3563};
3564
3565static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key)
3566{
3567 /* Mostly copied from BPy_IDGroup_Map_GetItem. */
3568 const char *name = PyUnicode_AsUTF8(key);
3569
3571
3572 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
3573 PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties");
3574 return nullptr;
3575 }
3576
3577 if (name == nullptr) {
3578 PyErr_SetString(PyExc_TypeError,
3579 "bpy_struct[key]: only strings are allowed as keys of ID properties");
3580 return nullptr;
3581 }
3582
3583 IDProperty *group = RNA_struct_idprops(&self->ptr.value(), false);
3584
3585 if (group == nullptr) {
3586 PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name);
3587 return nullptr;
3588 }
3589
3590 IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
3591
3592 if (idprop == nullptr) {
3593 PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name);
3594 return nullptr;
3595 }
3596
3597 return BPy_IDGroup_WrapData(self->ptr->owner_id, idprop, group);
3598}
3599
3600static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObject *value)
3601{
3603
3604 IDProperty *group = RNA_struct_idprops(&self->ptr.value(), true);
3605
3606#ifdef USE_PEDANTIC_WRITE
3607 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), key)) {
3608 return -1;
3609 }
3610#endif /* USE_PEDANTIC_WRITE */
3611
3612 if (group == nullptr) {
3613 PyErr_SetString(PyExc_TypeError,
3614 "bpy_struct[key] = val: id properties not supported for this type");
3615 return -1;
3616 }
3617
3618 if (value && BPy_StructRNA_Check(value)) {
3619 BPy_StructRNA *val = (BPy_StructRNA *)value;
3620 if (val && self->ptr->type && val->ptr->type) {
3621 if (!RNA_struct_idprops_datablock_allowed(self->ptr->type) &&
3623 {
3624 PyErr_SetString(
3625 PyExc_TypeError,
3626 "bpy_struct[key] = val: data-block id properties not supported for this type");
3627 return -1;
3628 }
3629 }
3630 }
3631
3632 return BPy_Wrap_SetMapItem(group, key, value);
3633}
3634
3635static PyMappingMethods pyrna_struct_as_mapping = {
3636 /*mp_length*/ (lenfunc) nullptr,
3637 /*mp_subscript*/ (binaryfunc)pyrna_struct_subscript,
3638 /*mp_ass_subscript*/ (objobjargproc)pyrna_struct_ass_subscript,
3639};
3640
3642 /* Wrap. */
3643 pyrna_struct_keys_doc,
3644 ".. method:: keys()\n"
3645 "\n"
3646 " Returns the keys of this objects custom properties (matches Python's\n"
3647 " dictionary function of the same name).\n"
3648 "\n"
3649 " :return: custom property keys.\n"
3650 " :rtype: :class:`idprop.types.IDPropertyGroupViewKeys`\n"
3653{
3655
3656 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
3657 PyErr_SetString(PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties");
3658 return nullptr;
3659 }
3660
3661 /* `group` may be nullptr. */
3662 IDProperty *group = RNA_struct_idprops(&self->ptr.value(), false);
3663 return BPy_Wrap_GetKeys_View_WithID(self->ptr->owner_id, group);
3664}
3665
3667 /* Wrap. */
3668 pyrna_struct_items_doc,
3669 ".. method:: items()\n"
3670 "\n"
3671 " Returns the items of this objects custom properties (matches Python's\n"
3672 " dictionary function of the same name).\n"
3673 "\n"
3674 " :return: custom property key, value pairs.\n"
3675 " :rtype: :class:`idprop.types.IDPropertyGroupViewItems`\n"
3678{
3680
3681 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
3682 PyErr_SetString(PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties");
3683 return nullptr;
3684 }
3685
3686 /* `group` may be nullptr. */
3687 IDProperty *group = RNA_struct_idprops(&self->ptr.value(), false);
3688 return BPy_Wrap_GetItems_View_WithID(self->ptr->owner_id, group);
3689}
3690
3692 /* Wrap. */
3693 pyrna_struct_values_doc,
3694 ".. method:: values()\n"
3695 "\n"
3696 " Returns the values of this objects custom properties (matches Python's\n"
3697 " dictionary function of the same name).\n"
3698 "\n"
3699 " :return: custom property values.\n"
3700 " :rtype: :class:`idprop.types.IDPropertyGroupViewValues`\n"
3703{
3705
3706 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
3707 PyErr_SetString(PyExc_TypeError,
3708 "bpy_struct.values(): this type doesn't support IDProperties");
3709 return nullptr;
3710 }
3711
3712 /* `group` may be nullptr. */
3713 IDProperty *group = RNA_struct_idprops(&self->ptr.value(), false);
3714 return BPy_Wrap_GetValues_View_WithID(self->ptr->owner_id, group);
3715}
3716
3718 /* Wrap. */
3719 pyrna_struct_is_property_set_doc,
3720 ".. method:: is_property_set(property, /, *, ghost=True)\n"
3721 "\n"
3722 " Check if a property is set, use for testing operator properties.\n"
3723 "\n"
3724 " :arg property: Property name.\n"
3725 " :type property: str\n"
3726 " :arg ghost: Used for operators that re-run with previous settings.\n"
3727 " In this case the property is not marked as set,\n"
3728 " yet the value from the previous execution is used.\n"
3729 "\n"
3730 " In rare cases you may want to set this option to false.\n"
3731 "\n"
3732 " :type ghost: bool\n"
3733 " :return: True when the property has been set.\n"
3734 " :rtype: bool\n");
3735static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args, PyObject *kw)
3736{
3737 PropertyRNA *prop;
3738 const char *name;
3739 bool use_ghost = true;
3740
3742
3743 static const char *_keywords[] = {"", "ghost", nullptr};
3744 static _PyArg_Parser _parser = {
3746 "s" /* `name` (positional). */
3747 "|$" /* Optional keyword only arguments. */
3748 "O&" /* `ghost` */
3749 ":is_property_set",
3750 _keywords,
3751 nullptr,
3752 };
3753 if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &name, PyC_ParseBool, &use_ghost)) {
3754 return nullptr;
3755 }
3756
3757 if ((prop = RNA_struct_find_property(&self->ptr.value(), name)) == nullptr) {
3758 PyErr_Format(PyExc_TypeError,
3759 "%.200s.is_property_set(\"%.200s\") not found",
3760 RNA_struct_identifier(self->ptr->type),
3761 name);
3762 return nullptr;
3763 }
3764
3765 return PyBool_FromLong(RNA_property_is_set_ex(&self->ptr.value(), prop, use_ghost));
3766}
3767
3769 /* Wrap. */
3770 pyrna_struct_property_unset_doc,
3771 ".. method:: property_unset(property, /)\n"
3772 "\n"
3773 " Unset a property, will use default value afterward.\n"
3774 "\n"
3775 " :arg property: Property name.\n"
3776 " :type property: str\n");
3777static PyObject *pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args)
3778{
3779 PropertyRNA *prop;
3780 const char *name;
3781
3783
3784 if (!PyArg_ParseTuple(args, "s:property_unset", &name)) {
3785 return nullptr;
3786 }
3787
3788 if ((prop = RNA_struct_find_property(&self->ptr.value(), name)) == nullptr) {
3789 PyErr_Format(PyExc_TypeError,
3790 "%.200s.property_unset(\"%.200s\") not found",
3791 RNA_struct_identifier(self->ptr->type),
3792 name);
3793 return nullptr;
3794 }
3795
3796 RNA_property_unset(&self->ptr.value(), prop);
3797
3798 Py_RETURN_NONE;
3799}
3800
3802 /* Wrap. */
3803 pyrna_struct_is_property_hidden_doc,
3804 ".. method:: is_property_hidden(property, /)\n"
3805 "\n"
3806 " Check if a property is hidden.\n"
3807 "\n"
3808 " :arg property: Property name.\n"
3809 " :type property: str\n"
3810 " :return: True when the property is hidden.\n"
3811 " :rtype: bool\n");
3812static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *args)
3813{
3814 PropertyRNA *prop;
3815 const char *name;
3816
3818
3819 if (!PyArg_ParseTuple(args, "s:is_property_hidden", &name)) {
3820 return nullptr;
3821 }
3822
3823 if ((prop = RNA_struct_find_property(&self->ptr.value(), name)) == nullptr) {
3824 PyErr_Format(PyExc_TypeError,
3825 "%.200s.is_property_hidden(\"%.200s\") not found",
3826 RNA_struct_identifier(self->ptr->type),
3827 name);
3828 return nullptr;
3829 }
3830
3831 return PyBool_FromLong(RNA_property_flag(prop) & PROP_HIDDEN);
3832}
3833
3835 /* Wrap. */
3836 pyrna_struct_is_property_readonly_doc,
3837 ".. method:: is_property_readonly(property, /)\n"
3838 "\n"
3839 " Check if a property is readonly.\n"
3840 "\n"
3841 " :arg property: Property name.\n"
3842 " :type property: str\n"
3843 " :return: True when the property is readonly (not writable).\n"
3844 " :rtype: bool\n");
3845static PyObject *pyrna_struct_is_property_readonly(BPy_StructRNA *self, PyObject *args)
3846{
3847 PropertyRNA *prop;
3848 const char *name;
3849
3851
3852 if (!PyArg_ParseTuple(args, "s:is_property_readonly", &name)) {
3853 return nullptr;
3854 }
3855
3856 if ((prop = RNA_struct_find_property(&self->ptr.value(), name)) == nullptr) {
3857 PyErr_Format(PyExc_TypeError,
3858 "%.200s.is_property_readonly(\"%.200s\") not found",
3859 RNA_struct_identifier(self->ptr->type),
3860 name);
3861 return nullptr;
3862 }
3863
3864 return PyBool_FromLong(!RNA_property_editable(&self->ptr.value(), prop));
3865}
3866
3868 /* Wrap. */
3869 pyrna_struct_is_property_overridable_library_doc,
3870 ".. method:: is_property_overridable_library(property, /)\n"
3871 "\n"
3872 " Check if a property is overridable.\n"
3873 "\n"
3874 " :arg property: Property name.\n"
3875 " :type property: str\n"
3876 " :return: True when the property is overridable.\n"
3877 " :rtype: bool\n");
3879{
3880 PropertyRNA *prop;
3881 const char *name;
3882
3884
3885 if (!PyArg_ParseTuple(args, "s:is_property_overridable_library", &name)) {
3886 return nullptr;
3887 }
3888
3889 if ((prop = RNA_struct_find_property(&self->ptr.value(), name)) == nullptr) {
3890 PyErr_Format(PyExc_TypeError,
3891 "%.200s.is_property_overridable_library(\"%.200s\") not found",
3892 RNA_struct_identifier(self->ptr->type),
3893 name);
3894 return nullptr;
3895 }
3896
3897 return PyBool_FromLong(long(RNA_property_overridable_get(&self->ptr.value(), prop)));
3898}
3899
3901 /* Wrap. */
3902 pyrna_struct_property_overridable_library_set_doc,
3903 ".. method:: property_overridable_library_set(property, overridable, /)\n"
3904 "\n"
3905 " Define a property as overridable or not (only for custom properties!).\n"
3906 "\n"
3907 " :arg property: Property name.\n"
3908 " :type property: str\n"
3909 " :arg overridable: Overridable status to set.\n"
3910 " :type overridable: bool\n"
3911 " :return: True when the overridable status of the property was successfully set.\n"
3912 " :rtype: bool\n");
3914{
3915 PropertyRNA *prop;
3916 const char *name;
3917 int is_overridable;
3918
3920
3921 if (!PyArg_ParseTuple(args, "sp:property_overridable_library_set", &name, &is_overridable)) {
3922 return nullptr;
3923 }
3924
3925 if ((prop = RNA_struct_find_property(&self->ptr.value(), name)) == nullptr) {
3926 PyErr_Format(PyExc_TypeError,
3927 "%.200s.property_overridable_library_set(\"%.200s\") not found",
3928 RNA_struct_identifier(self->ptr->type),
3929 name);
3930 return nullptr;
3931 }
3932
3933 return PyBool_FromLong(
3934 long(RNA_property_overridable_library_set(&self->ptr.value(), prop, bool(is_overridable))));
3935}
3936
3938 /* Wrap. */
3939 pyrna_struct_path_resolve_doc,
3940 ".. method:: path_resolve(path, coerce=True, /)\n"
3941 "\n"
3942 " Returns the property from the path, raise an exception when not found.\n"
3943 "\n"
3944 " :arg path: path which this property resolves.\n"
3945 " :type path: str\n"
3946 " :arg coerce: optional argument, when True, the property will be converted\n"
3947 " into its Python representation.\n"
3948 " :type coerce: bool\n"
3949 " :return: Property value or property object.\n"
3950 " :rtype: Any | :class:`bpy.types.bpy_prop`\n");
3951static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *args)
3952{
3953 const char *path;
3954 PyObject *coerce = Py_True;
3955 PointerRNA r_ptr;
3956 PropertyRNA *r_prop;
3957 int index = -1;
3958
3960
3961 if (!PyArg_ParseTuple(args, "s|O!:path_resolve", &path, &PyBool_Type, &coerce)) {
3962 return nullptr;
3963 }
3964
3965 if (RNA_path_resolve_full_maybe_null(&self->ptr.value(), path, &r_ptr, &r_prop, &index)) {
3966 if (r_prop) {
3967 if (index != -1) {
3968 if (index >= RNA_property_array_length(&r_ptr, r_prop) || index < 0) {
3969 PyErr_Format(PyExc_IndexError,
3970 "%.200s.path_resolve(\"%.200s\") index out of range",
3971 RNA_struct_identifier(self->ptr->type),
3972 path);
3973 return nullptr;
3974 }
3975
3976 return pyrna_array_index(&r_ptr, r_prop, index);
3977 }
3978
3979 if (coerce == Py_False) {
3980 return pyrna_prop_CreatePyObject(&r_ptr, r_prop);
3981 }
3982
3983 return pyrna_prop_to_py(&r_ptr, r_prop);
3984 }
3985
3986 return pyrna_struct_CreatePyObject(&r_ptr);
3987 }
3988
3989 PyErr_Format(PyExc_ValueError,
3990 "%.200s.path_resolve(\"%.200s\") could not be resolved",
3991 RNA_struct_identifier(self->ptr->type),
3992 path);
3993 return nullptr;
3994}
3995
3997 /* Wrap. */
3998 pyrna_struct_path_from_module_doc,
3999 ".. method:: path_from_module(property=\"\", index=-1, /)\n"
4000 "\n"
4001 " Returns the full data path to this struct (as a string) from the bpy module.\n"
4002 "\n"
4003 " :arg property: Optional property name to get the full path from\n"
4004 " :type property: str\n"
4005 " :arg index: Optional index of the property.\n"
4006 " \"-1\" means that the property has no indices.\n"
4007 " :type index: int\n"
4008 " :return: The full path to the data.\n"
4009 " :rtype: str\n"
4010 "\n"
4011 " :raises ValueError:\n"
4012 " if the input data cannot be converted into a full data path.\n"
4013 "\n"
4014 " .. note:: Even if all input data is correct, this function might\n"
4015 " error out because Blender cannot derive a valid path.\n"
4016 " The incomplete path will be printed in the error message.\n");
4017static PyObject *pyrna_struct_path_from_module(BPy_StructRNA *self, PyObject *args)
4018{
4019 const char *error_prefix = "path_from_module(...)";
4020 const char *name = nullptr;
4021 PropertyRNA *prop;
4022 int index = -1;
4023
4025
4026 if (!PyArg_ParseTuple(args, "|si:path_from_module", &name, &index)) {
4027 return nullptr;
4028 }
4029 if (index < -1) {
4030 PyErr_Format(PyExc_ValueError, "%s: indices below -1 are not supported", error_prefix);
4031 return nullptr;
4032 }
4033
4034 std::optional<std::string> path;
4035 if (name) {
4036 prop = RNA_struct_find_property(&self->ptr.value(), name);
4037 if (prop == nullptr) {
4038 PyErr_Format(PyExc_AttributeError,
4039 "%.200s.path_from_module(\"%.200s\") not found",
4040 RNA_struct_identifier(self->ptr->type),
4041 name);
4042 return nullptr;
4043 }
4044 path = RNA_path_full_property_py_ex(&self->ptr.value(), prop, index, true);
4045 }
4046 else {
4047 if (RNA_struct_is_ID(self->ptr->type)) {
4048 path = RNA_path_full_ID_py(self->ptr->owner_id);
4049 }
4050 else {
4051 path = RNA_path_full_struct_py(&self->ptr.value());
4052 }
4053 }
4054
4055 if (!path) {
4056 if (name) {
4057 PyErr_Format(PyExc_ValueError,
4058 "%.200s.path_from_module(\"%s\", %d) found, but does not support path creation",
4059 RNA_struct_identifier(self->ptr->type),
4060 name,
4061 index);
4062 }
4063 else {
4064 PyErr_Format(PyExc_ValueError,
4065 "%.200s.path_from_module() does not support path creation for this type",
4066 RNA_struct_identifier(self->ptr->type));
4067 }
4068 return nullptr;
4069 }
4070
4071 if (path.value().back() == '.') {
4072 PyErr_Format(PyExc_ValueError,
4073 "%.200s.path_from_module() could not derive a complete path for this type.\n"
4074 "Only got \"%.200s\" as an incomplete path",
4075 RNA_struct_identifier(self->ptr->type),
4076 path.value().c_str());
4077 return nullptr;
4078 }
4079
4080 return PyC_UnicodeFromStdStr(path.value());
4081}
4082
4084 /* Wrap. */
4085 pyrna_prop_path_from_module_doc,
4086 ".. method:: path_from_module()\n"
4087 "\n"
4088 " Returns the full data path to this struct (as a string) from the bpy module.\n"
4089 "\n"
4090 " :return: The full path to the data.\n"
4091 " :rtype: str\n"
4092 "\n"
4093 " :raises ValueError:\n"
4094 " if the input data cannot be converted into a full data path.\n"
4095 "\n"
4096 " .. note:: Even if all input data is correct, this function might\n"
4097 " error out because Blender cannot derive a valid path.\n"
4098 " The incomplete path will be printed in the error message.\n");
4100{
4101 PropertyRNA *prop = self->prop;
4102
4103 const std::optional<std::string> path = RNA_path_full_property_py_ex(
4104 &self->ptr.value(), prop, -1, true);
4105
4106 if (!path) {
4107 PyErr_Format(PyExc_ValueError,
4108 "%.200s.%.200s.path_from_module() does not support path creation for this type",
4109 RNA_struct_identifier(self->ptr->type),
4111 return nullptr;
4112 }
4113
4114 if (path.value().back() == '.') {
4115 PyErr_Format(
4116 PyExc_ValueError,
4117 "%.200s.%.200s.path_from_module() could not derive a complete path for this type.\n"
4118 "Only got \"%.200s\" as an incomplete path",
4119 RNA_struct_identifier(self->ptr->type),
4121 path.value().c_str());
4122 return nullptr;
4123 }
4124
4125 return PyC_UnicodeFromStdStr(path.value());
4126}
4127
4129 /* Wrap. */
4130 pyrna_struct_path_from_id_doc,
4131 ".. method:: path_from_id(property=\"\", /)\n"
4132 "\n"
4133 " Returns the data path from the ID to this object (string).\n"
4134 "\n"
4135 " :arg property: Optional property name which can be used if the path is\n"
4136 " to a property of this object.\n"
4137 " :type property: str\n"
4138 " :return: The path from :class:`bpy.types.bpy_struct.id_data`\n"
4139 " to this struct and property (when given).\n"
4140 " :rtype: str\n");
4141static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
4142{
4143 const char *name = nullptr;
4144 PropertyRNA *prop;
4145
4147
4148 if (!PyArg_ParseTuple(args, "|s:path_from_id", &name)) {
4149 return nullptr;
4150 }
4151
4152 std::optional<std::string> path;
4153 if (name) {
4154 prop = RNA_struct_find_property(&self->ptr.value(), name);
4155 if (prop == nullptr) {
4156 PyErr_Format(PyExc_AttributeError,
4157 "%.200s.path_from_id(\"%.200s\") not found",
4158 RNA_struct_identifier(self->ptr->type),
4159 name);
4160 return nullptr;
4161 }
4162
4163 path = RNA_path_from_ID_to_property(&self->ptr.value(), prop);
4164 }
4165 else {
4166 path = RNA_path_from_ID_to_struct(&self->ptr.value());
4167 }
4168
4169 if (!path) {
4170 if (name) {
4171 PyErr_Format(PyExc_ValueError,
4172 "%.200s.path_from_id(\"%s\") found, but does not support path creation",
4173 RNA_struct_identifier(self->ptr->type),
4174 name);
4175 }
4176 else {
4177 PyErr_Format(PyExc_ValueError,
4178 "%.200s.path_from_id() does not support path creation for this type",
4179 RNA_struct_identifier(self->ptr->type));
4180 }
4181 return nullptr;
4182 }
4183
4184 return PyC_UnicodeFromStdStr(path.value());
4185}
4186
4188 /* Wrap. */
4189 pyrna_prop_path_from_id_doc,
4190 ".. method:: path_from_id()\n"
4191 "\n"
4192 " Returns the data path from the ID to this property (string).\n"
4193 "\n"
4194 " :return: The path from :class:`bpy.types.bpy_struct.id_data` to this property.\n"
4195 " :rtype: str\n");
4197{
4198 PropertyRNA *prop = self->prop;
4199
4200 const std::optional<std::string> path = RNA_path_from_ID_to_property(&self->ptr.value(),
4201 self->prop);
4202
4203 if (!path) {
4204 PyErr_Format(PyExc_ValueError,
4205 "%.200s.%.200s.path_from_id() does not support path creation for this type",
4206 RNA_struct_identifier(self->ptr->type),
4208 return nullptr;
4209 }
4210
4211 return PyC_UnicodeFromStdStr(path.value());
4212}
4213
4215 /* Wrap. */
4216 pyrna_prop_as_bytes_doc,
4217 ".. method:: as_bytes()\n"
4218 "\n"
4219 " Returns this string property as a byte rather than a Python string.\n"
4220 "\n"
4221 " :return: The string as bytes.\n"
4222 " :rtype: bytes\n");
4224{
4225
4226 if (RNA_property_type(self->prop) != PROP_STRING) {
4227 PyErr_Format(PyExc_TypeError,
4228 "%.200s.%.200s.as_bytes() must be a string",
4229 RNA_struct_identifier(self->ptr->type),
4231 return nullptr;
4232 }
4233
4234 PyObject *ret;
4235 char buf_fixed[256], *buf;
4236 int buf_len;
4237
4239 &self->ptr.value(), self->prop, buf_fixed, sizeof(buf_fixed), &buf_len);
4240
4241 ret = PyBytes_FromStringAndSize(buf, buf_len);
4242
4243 if (buf_fixed != buf) {
4244 MEM_freeN(buf);
4245 }
4246
4247 return ret;
4248}
4249
4251 /* Wrap. */
4252 pyrna_prop_update_doc,
4253 ".. method:: update()\n"
4254 "\n"
4255 " Execute the properties update callback.\n"
4256 "\n"
4257 " .. note::\n"
4258 " This is called when assigning a property,\n"
4259 " however in rare cases it's useful to call explicitly.\n");
4261{
4262 RNA_property_update(BPY_context_get(), &self->ptr.value(), self->prop);
4263 Py_RETURN_NONE;
4264}
4265
4267 /* Wrap. */
4268 pyrna_struct_type_recast_doc,
4269 ".. method:: type_recast()\n"
4270 "\n"
4271 " Return a new instance, this is needed because types\n"
4272 " such as textures can be changed at runtime.\n"
4273 "\n"
4274 " :return: a new instance of this object with the type initialized again.\n"
4275 " :rtype: :class:`bpy.types.bpy_struct`\n");
4277{
4278
4280
4281 PointerRNA r_ptr = RNA_pointer_recast(&self->ptr.value());
4282 return pyrna_struct_CreatePyObject(&r_ptr);
4283}
4284
4288static PyObject *pyrna_struct_bl_rna_find_subclass_recursive(PyObject *cls, const char *id)
4289{
4290 PyObject *ret_test = nullptr;
4291 PyObject *subclasses = (PyObject *)((PyTypeObject *)cls)->tp_subclasses;
4292 if (subclasses) {
4293 /* Unfortunately we can't use the dict key because Python class names
4294 * don't match the bl_idname used internally. */
4295 BLI_assert(PyDict_CheckExact(subclasses));
4296 PyObject *key = nullptr;
4297 Py_ssize_t pos = 0;
4298 PyObject *value = nullptr;
4299 while (PyDict_Next(subclasses, &pos, &key, &value)) {
4300 BLI_assert(PyWeakref_CheckRef(value));
4301 PyObject *subcls = PyWeakref_GET_OBJECT(value);
4302 if (subcls != Py_None) {
4303 BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)subcls)->tp_dict,
4305 if (py_srna) {
4306 StructRNA *srna = static_cast<StructRNA *>(py_srna->ptr->data);
4307 if (STREQ(id, RNA_struct_identifier(srna))) {
4308 ret_test = subcls;
4309 break;
4310 }
4311 }
4312 ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id);
4313 if (ret_test) {
4314 break;
4315 }
4316 }
4317 }
4318 }
4319 return ret_test;
4320}
4321
4323 /* Wrap. */
4324 pyrna_struct_bl_rna_get_subclass_py_doc,
4325 ".. classmethod:: bl_rna_get_subclass_py(id, default=None, /)\n"
4326 "\n"
4327 " :arg id: The RNA type identifier.\n"
4328 " :type id: str\n"
4329 " :return: The class or default when not found.\n"
4330 " :rtype: type\n");
4331static PyObject *pyrna_struct_bl_rna_get_subclass_py(PyObject *cls, PyObject *args)
4332{
4333 char *id;
4334 PyObject *ret_default = Py_None;
4335
4336 if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass_py", &id, &ret_default)) {
4337 return nullptr;
4338 }
4340 if (ret == nullptr) {
4341 ret = ret_default;
4342 }
4343 return Py_NewRef(ret);
4344}
4345
4347 /* Wrap. */
4348 pyrna_struct_bl_rna_get_subclass_doc,
4349 ".. classmethod:: bl_rna_get_subclass(id, default=None, /)\n"
4350 "\n"
4351 " :arg id: The RNA type identifier.\n"
4352 " :type id: str\n"
4353 " :return: The RNA type or default when not found.\n"
4354 " :rtype: :class:`bpy.types.Struct` subclass\n");
4355static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args)
4356{
4357 const char *id;
4358 PyObject *ret_default = Py_None;
4359
4360 if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass", &id, &ret_default)) {
4361 return nullptr;
4362 }
4363
4364 const BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)cls)->tp_dict,
4366 if (py_srna == nullptr) {
4367 PyErr_SetString(PyExc_ValueError, "Not a registered class");
4368 return nullptr;
4369 }
4370 const StructRNA *srna_base = static_cast<const StructRNA *>(py_srna->ptr->data);
4371
4372 if (srna_base == &RNA_Node) {
4373 /* If the given idname is an alias, translate it to the proper idname. */
4375
4377 if (nt) {
4378 PointerRNA ptr = RNA_pointer_create_discrete(nullptr, &RNA_Struct, nt->rna_ext.srna);
4380 }
4381 }
4382 else {
4383 /* TODO: panels, menus etc. */
4384 PyErr_Format(
4385 PyExc_ValueError, "Class type \"%.200s\" not supported", RNA_struct_identifier(srna_base));
4386 return nullptr;
4387 }
4388
4389 return Py_NewRef(ret_default);
4390}
4391
4393 /* Wrap. */
4394 pyrna_struct_get_ancestors_doc,
4395 ".. method:: rna_ancestors()\n"
4396 "\n"
4397 " Return the chain of data containing this struct, if known.\n"
4398 " The first item is the root (typically an ID), the last one is the immediate parent.\n"
4399 " May be empty.\n"
4400 "\n"
4401 " :return: a list of this object's ancestors.\n"
4402 " :rtype: list[:class:`bpy.types.bpy_struct`]\n");
4404{
4406
4407 PyObject *ret;
4408 const int ancestors_num(self->ptr->ancestors.size());
4409
4410 ret = PyList_New(ancestors_num);
4411
4412 for (int i = 0; i < ancestors_num; i++) {
4413 PointerRNA ancestor_ptr = RNA_pointer_create_from_ancestor(self->ptr.value(), i);
4414 PyObject *ancestor = pyrna_struct_CreatePyObject(&ancestor_ptr);
4415 PyList_SET_ITEM(ret, i, ancestor);
4416 }
4417
4418 return ret;
4419}
4420
4421static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict)
4422{
4423 PyObject *list_tmp;
4424
4425 list_tmp = PyDict_Keys(dict);
4426 PyList_SetSlice(list, INT_MAX, INT_MAX, list_tmp);
4427 Py_DECREF(list_tmp);
4428}
4429
4430static void pyrna_dir_members_py(PyObject *list, PyObject *self)
4431{
4432 PyObject *dict;
4433 PyObject **dict_ptr;
4434
4435 dict_ptr = _PyObject_GetDictPtr(self);
4436
4437 if (dict_ptr && (dict = *dict_ptr)) {
4439 }
4440
4441 dict = ((PyTypeObject *)Py_TYPE(self))->tp_dict;
4442 if (dict) {
4444 }
4445
4446 /* Since this is least common case, handle it last. */
4448 BPy_PropertyRNA *self_prop = (BPy_PropertyRNA *)self;
4449 if (RNA_property_type(self_prop->prop) == PROP_COLLECTION) {
4450 PointerRNA r_ptr;
4451
4452 if (RNA_property_collection_type_get(&self_prop->ptr.value(), self_prop->prop, &r_ptr)) {
4453 PyObject *cls = pyrna_struct_Subtype(&r_ptr); /* borrows */
4454 dict = ((PyTypeObject *)cls)->tp_dict;
4456 Py_DECREF(cls);
4457 }
4458 }
4459 }
4460}
4461
4462static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
4463{
4464 const char *idname;
4465
4466 /* For looping over attributes and functions. */
4467 PropertyRNA *iterprop;
4468
4469 {
4470 PointerRNA tptr = RNA_pointer_create_discrete(nullptr, &RNA_Struct, ptr->type);
4471 iterprop = RNA_struct_find_property(&tptr, "functions");
4472
4473 RNA_PROP_BEGIN (&tptr, itemptr, iterprop) {
4474 FunctionRNA *func = static_cast<FunctionRNA *>(itemptr.data);
4475 if (RNA_function_defined(func)) {
4476 idname = RNA_function_identifier(static_cast<FunctionRNA *>(itemptr.data));
4477 PyList_APPEND(list, PyUnicode_FromString(idname));
4478 }
4479 }
4481 }
4482
4483 {
4484 /*
4485 * Collect RNA attributes
4486 */
4487 iterprop = RNA_struct_iterator_property(ptr->type);
4488
4489 BPy_NamePropAsPyObject_Cache nameprop_cache = {nullptr};
4490 RNA_PROP_BEGIN (ptr, itemptr, iterprop) {
4491 /* Custom-properties are exposed using `__getitem__`, exclude from `__dir__`. */
4492 if (RNA_property_is_idprop(static_cast<const PropertyRNA *>(itemptr.data))) {
4493 continue;
4494 }
4495 if (PyObject *name_py = pyrna_struct_get_nameprop_as_pyobject(&itemptr, nameprop_cache)) {
4496 PyList_APPEND(list, name_py);
4497 }
4498 }
4500 }
4501}
4502
4504{
4505 PyObject *ret;
4506
4508
4509 /* Include this in case this instance is a subtype of a Python class
4510 * In these instances we may want to return a function or variable provided by the subtype. */
4511 ret = PyList_New(0);
4512
4514 pyrna_dir_members_py(ret, (PyObject *)self);
4515 }
4516
4517 pyrna_dir_members_rna(ret, &self->ptr.value());
4518
4519 if (self->ptr->type == &RNA_Context) {
4520 ListBase lb = CTX_data_dir_get(static_cast<const bContext *>(self->ptr->data));
4521
4522 LISTBASE_FOREACH (LinkData *, link, &lb) {
4523 PyList_APPEND(ret, PyUnicode_FromString(static_cast<const char *>(link->data)));
4524 }
4525
4526 BLI_freelistN(&lb);
4527 }
4528
4529 {
4530 /* set(), this is needed to remove-doubles because the deferred
4531 * register-props will be in both the Python __dict__ and accessed as RNA */
4532
4533 PyObject *set = PySet_New(ret);
4534
4535 Py_DECREF(ret);
4536 ret = PySequence_List(set);
4537 Py_DECREF(set);
4538 }
4539
4540 return ret;
4541}
4542
4544 /* Wrap. */
4545 pyrna_struct_id_properties_ensure_doc,
4546 ".. method:: id_properties_ensure()\n"
4547 "\n"
4548 " :return: the parent group for an RNA struct's custom IDProperties.\n"
4549 " :rtype: :class:`idprop.types.IDPropertyGroup`\n");
4551{
4553
4554 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
4555 PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties");
4556 return nullptr;
4557 }
4558
4559 IDProperty *idprops = RNA_struct_idprops(&self->ptr.value(), true);
4560
4561 /* This is a paranoid check that theoretically might not be necessary.
4562 * It allows the possibility that some structs can't ensure IDProperties. */
4563 if (idprops == nullptr) {
4564 return Py_None;
4565 }
4566
4567 BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type);
4568 group->owner_id = self->ptr->owner_id;
4569 group->prop = idprops;
4570 group->parent = nullptr;
4571 return (PyObject *)group;
4572}
4573
4575 /* Wrap. */
4576 pyrna_struct_id_properties_ui_doc,
4577 ".. method:: id_properties_ui(key, /)\n"
4578 "\n"
4579 " :return: Return an object used to manage an IDProperty's UI data.\n"
4580 " :arg key: String name of the property.\n"
4581 " :type key: str.\n"
4582 " :rtype: :class:`bpy.types.IDPropertyUIManager`\n");
4583static PyObject *pyrna_struct_id_properties_ui(BPy_StructRNA *self, PyObject *args)
4584{
4586
4587 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
4588 PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties");
4589 return nullptr;
4590 }
4591
4592 const char *key;
4593 if (!PyArg_ParseTuple(args, "s:ui_data", &key)) {
4594 return nullptr;
4595 }
4596
4597 IDProperty *parent_group = RNA_struct_idprops(&self->ptr.value(), true);
4598
4599 /* This is a paranoid check that theoretically might not be necessary.
4600 * It allows the possibility that some structs can't ensure IDProperties. */
4601 if (parent_group == nullptr) {
4602 return Py_None;
4603 }
4604
4605 IDProperty *property = IDP_GetPropertyFromGroup(parent_group, key);
4606 if (property == nullptr) {
4607 PyErr_SetString(PyExc_KeyError, "Property not found in IDProperty group");
4608 return nullptr;
4609 }
4610
4611 if (!IDP_ui_data_supported(property)) {
4612 PyErr_Format(PyExc_TypeError, "IDProperty \"%s\" does not support UI data", property->name);
4613 return nullptr;
4614 }
4615
4616 BPy_IDPropertyUIManager *ui_manager = PyObject_New(BPy_IDPropertyUIManager,
4618 ui_manager->property = property;
4619 return (PyObject *)ui_manager;
4620}
4621
4623 /* Wrap. */
4624 pyrna_struct_id_properties_clear_doc,
4625 ".. method:: id_properties_clear()\n"
4626 "\n"
4627 " :return: Remove the parent group for an RNA struct's custom IDProperties.\n");
4629{
4631
4632 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
4633 PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties");
4634 return nullptr;
4635 }
4636
4637 IDProperty **idprops = RNA_struct_idprops_p(&self->ptr.value());
4638
4639 if (*idprops) {
4640 IDP_FreeProperty(*idprops);
4641 *idprops = nullptr;
4642 }
4643
4644 Py_RETURN_NONE;
4645}
4646
4647/* ---------------getattr-------------------------------------------- */
4648static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
4649{
4650 const char *name = PyUnicode_AsUTF8(pyname);
4651 PyObject *ret;
4652 PropertyRNA *prop;
4653 FunctionRNA *func;
4654
4655 /* Allow `__class__` so `isinstance(ob, cls)` can be used without raising an exception. */
4657
4658 if (name == nullptr) {
4659 PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string");
4660 ret = nullptr;
4661 }
4662 else if (
4663 /* RNA can't start with a "_", so for __dict__ and similar we can skip using RNA lookups. */
4664 name[0] == '_')
4665 {
4666 /* Annoying exception, maybe we need to have different types for this... */
4667 if (STR_ELEM(name, "__getitem__", "__setitem__") && !RNA_struct_idprops_check(self->ptr->type))
4668 {
4669 PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type");
4670 ret = nullptr;
4671 }
4672 else {
4673 ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
4674 }
4675 }
4676 else if ((prop = RNA_struct_find_property(&self->ptr.value(), name))) {
4677 ret = pyrna_prop_to_py(&self->ptr.value(), prop);
4678 }
4679 /* RNA function only if callback is declared (no optional functions). */
4680 else if ((func = RNA_struct_find_function(self->ptr->type, name)) && RNA_function_defined(func))
4681 {
4682 ret = pyrna_func_CreatePyObject(&self->ptr.value(), func);
4683 }
4684 else if (self->ptr->type == &RNA_Context) {
4685 bContext *C = static_cast<bContext *>(self->ptr->data);
4686 if (C == nullptr) {
4687 PyErr_Format(PyExc_AttributeError,
4688 "bpy_struct: Context is 'null', cannot get \"%.200s\" from context",
4689 name);
4690 ret = nullptr;
4691 }
4692 else {
4693 PointerRNA newptr;
4695 PropertyRNA *newprop;
4696 int newindex;
4697 blender::StringRef newstr;
4698 std::optional<int64_t> newint;
4699 ContextDataType newtype;
4700
4701 /* An empty string is used to implement #CTX_data_dir_get,
4702 * without this check `getattr(context, "")` succeeds. */
4703 eContextResult done;
4704 if (name[0]) {
4706 C, name, &newptr, &newlb, &newprop, &newindex, &newstr, &newint, &newtype));
4707 }
4708 else {
4709 /* Fall through to built-in `getattr`. */
4711 }
4712
4713 if (done == CTX_RESULT_OK) {
4714 switch (newtype) {
4716 if (newptr.data == nullptr) {
4717 ret = Py_None;
4718 Py_INCREF(ret);
4719 }
4720 else {
4722 }
4723 break;
4725 if (newstr.is_empty()) {
4726 ret = Py_None;
4727 Py_INCREF(ret);
4728 }
4729 else {
4730 ret = PyUnicode_FromStringAndSize(newstr.data(), newstr.size());
4731 }
4732 break;
4733 }
4735 if (!newint.has_value()) {
4736 ret = Py_None;
4737 Py_INCREF(ret);
4738 }
4739 else {
4740 ret = PyLong_FromLong(*newint);
4741 }
4742 break;
4743 }
4745 ret = PyList_New(0);
4746 for (PointerRNA &ptr : newlb) {
4747 PyList_APPEND(ret, pyrna_struct_CreatePyObject(&ptr));
4748 }
4749 break;
4750 }
4752 if (newprop != nullptr) {
4753 /* Create pointer to parent ID, and path from ID to property. */
4754 PointerRNA idptr;
4755
4756 PointerRNA *base_ptr;
4757 std::optional<std::string> path_str;
4758
4759 if (newptr.owner_id) {
4760 path_str = RNA_path_from_ID_to_property(&newptr, newprop);
4761 idptr = RNA_id_pointer_create(newptr.owner_id);
4762 base_ptr = &idptr;
4763 }
4764 else {
4765 path_str = RNA_path_from_ptr_to_property_index(&newptr, newprop, 0, -1);
4766 base_ptr = &newptr;
4767 }
4768
4769 if (path_str) {
4770 ret = PyTuple_New(3);
4773 PyC_UnicodeFromStdStr(path_str.value()),
4774 PyLong_FromLong(newindex));
4775 }
4776 else {
4777 ret = Py_None;
4778 Py_INCREF(ret);
4779 }
4780 }
4781 else {
4782 ret = Py_None;
4783 Py_INCREF(ret);
4784 }
4785 break;
4786 }
4787 default:
4788 /* Should never happen. */
4789 BLI_assert_msg(0, "Invalid context type");
4790
4791 PyErr_Format(PyExc_AttributeError,
4792 "bpy_struct: Context type invalid %d, cannot get \"%.200s\" from context",
4793 newtype,
4794 name);
4795 ret = nullptr;
4796 break;
4797 }
4798 }
4799 else if (done == CTX_RESULT_NO_DATA) {
4800 ret = Py_None;
4801 Py_INCREF(ret);
4802 }
4803 else { /* Not found in the context. */
4804 /* Lookup the subclass. raise an error if it's not found. */
4805 ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
4806 }
4807 }
4808 }
4809 else {
4810#if 0
4811 PyErr_Format(PyExc_AttributeError, "bpy_struct: attribute \"%.200s\" not found", name);
4812 ret = nullptr;
4813#endif
4814 /* Include this in case this instance is a subtype of a Python class
4815 * In these instances we may want to return a function or variable provided by the subtype
4816 *
4817 * Also needed to return methods when it's not a subtype.
4818 */
4819
4820 /* The error raised here will be displayed */
4821 ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
4822 }
4823
4824 return ret;
4825}
4826
4827#if 0
4828static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname)
4829{
4830 PyObject *dict = *(_PyObject_GetDictPtr((PyObject *)self));
4831 if (UNLIKELY(dict == nullptr)) {
4832 return 0;
4833 }
4834
4835 return PyDict_Contains(dict, pyname);
4836}
4837#endif
4838
4839/* --------------- setattr------------------------------------------- */
4840
4841#if 0
4842static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *attr)
4843{
4844 PyObject *ret = PyType_Type.tp_getattro(cls, attr);
4845
4846/* Allows:
4847 * >>> bpy.types.Scene.foo = BoolProperty()
4848 * >>> bpy.types.Scene.foo
4849 * <bpy_struct, BoolProperty("foo")>
4850 * ...rather than returning the deferred class register tuple
4851 * as checked by BPy_PropDeferred_CheckTypeExact()
4852 *
4853 * Disable for now,
4854 * this is faking internal behavior in a way that's too tricky to maintain well. */
4855# if 0
4856 if ((ret == nullptr) /* || BPy_PropDeferred_CheckTypeExact(ret) */) {
4857 PyErr_Clear(); /* Clear error from tp_getattro. */
4858 StructRNA *srna = srna_from_self(cls, "StructRNA.__getattr__");
4859 if (srna) {
4860 PropertyRNA *prop = RNA_struct_type_find_property_no_base(srna, PyUnicode_AsUTF8(attr));
4861 if (prop) {
4862 PointerRNA tptr = RNA_pointer_create_discrete(nullptr, &RNA_Property, prop);
4864 }
4865 }
4866 if (ret == nullptr) {
4867 PyErr_Format(PyExc_AttributeError,
4868 "StructRNA.__getattr__: attribute \"%.200s\" not found",
4869 PyUnicode_AsUTF8(attr));
4870 }
4871 }
4872# endif
4873
4874 return ret;
4875}
4876#endif
4877
4878static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyObject *value)
4879{
4880 StructRNA *srna = srna_from_self(cls, "StructRNA.__setattr__");
4881 const bool is_deferred_prop = (value && BPy_PropDeferred_CheckTypeExact(value));
4882 const char *attr_str = PyUnicode_AsUTF8(attr);
4883
4884 if (srna && !pyrna_write_check() &&
4885 (is_deferred_prop || RNA_struct_type_find_property_no_base(srna, attr_str)))
4886 {
4887 PyErr_Format(PyExc_AttributeError,
4888 "pyrna_struct_meta_idprop_setattro() "
4889 "cannot set in readonly state '%.200s.%S'",
4890 ((PyTypeObject *)cls)->tp_name,
4891 attr);
4892 return -1;
4893 }
4894
4895 if (srna == nullptr) {
4896/* Allow setting on unregistered classes which can be registered later on. */
4897#if 0
4898 if (value && is_deferred_prop) {
4899 PyErr_Format(PyExc_AttributeError,
4900 "pyrna_struct_meta_idprop_setattro() unable to get srna from class '%.200s'",
4901 ((PyTypeObject *)cls)->tp_name);
4902 return -1;
4903 }
4904#endif
4905 /* srna_from_self may set an error. */
4906 PyErr_Clear();
4907 return PyType_Type.tp_setattro(cls, attr, value);
4908 }
4909
4910 if (value) {
4911 /* Check if the value is a property. */
4912 if (is_deferred_prop) {
4913 const int ret = deferred_register_prop(srna, attr, value);
4914 if (ret == -1) {
4915 /* Error set. */
4916 return ret;
4917 }
4918
4919 /* pass through and assign to the classes __dict__ as well
4920 * so when the value isn't assigned it still creates the RNA property,
4921 * but gets confusing from script writers POV if the assigned value can't be read back. */
4922 }
4923 else {
4924 /* Remove existing property if it's set or we also end up with confusion. */
4925 RNA_def_property_free_identifier(srna, attr_str); /* Ignore on failure. */
4926 }
4927 }
4928 else { /* __delattr__ */
4929 /* First find if this is a registered property. */
4930 const int ret = RNA_def_property_free_identifier(srna, attr_str);
4931 if (ret == -1) {
4932 PyErr_Format(
4933 PyExc_TypeError, "struct_meta_idprop.detattr(): '%s' not a dynamic property", attr_str);
4934 return -1;
4935 }
4936 }
4937
4938 /* Fall back to standard Python's `delattr/setattr`. */
4939 return PyType_Type.tp_setattro(cls, attr, value);
4940}
4941
4942static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject *value)
4943{
4944 const char *name = PyUnicode_AsUTF8(pyname);
4945 PropertyRNA *prop = nullptr;
4946
4948
4949#ifdef USE_PEDANTIC_WRITE
4950 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), pyname)) {
4951 return -1;
4952 }
4953#endif /* USE_PEDANTIC_WRITE */
4954
4955 if (name == nullptr) {
4956 PyErr_SetString(PyExc_AttributeError, "bpy_struct: __setattr__ must be a string");
4957 return -1;
4958 }
4959 if (name[0] != '_' && (prop = RNA_struct_find_property(&self->ptr.value(), name))) {
4960 if (!RNA_property_editable_flag(&self->ptr.value(), prop)) {
4961 PyErr_Format(PyExc_AttributeError,
4962 "bpy_struct: attribute \"%.200s\" from \"%.200s\" is read-only",
4964 RNA_struct_identifier(self->ptr->type));
4965 return -1;
4966 }
4967 }
4968 else if (self->ptr->type == &RNA_Context) {
4969 /* Code just raises correct error, context prop's can't be set,
4970 * unless it's a part of the py class. */
4971 bContext *C = static_cast<bContext *>(self->ptr->data);
4972 if (C == nullptr) {
4973 PyErr_Format(PyExc_AttributeError,
4974 "bpy_struct: Context is 'null', cannot set \"%.200s\" from context",
4975 name);
4976 return -1;
4977 }
4978
4979 PointerRNA newptr;
4981 PropertyRNA *newprop;
4982 int newindex;
4983 blender::StringRef newstr;
4984 std::optional<int64_t> newint;
4985 ContextDataType newtype;
4986
4987 const eContextResult done = eContextResult(
4988 CTX_data_get(C, name, &newptr, &newlb, &newprop, &newindex, &newstr, &newint, &newtype));
4989
4990 if (done == CTX_RESULT_OK) {
4991 PyErr_Format(
4992 PyExc_AttributeError, "bpy_struct: Context property \"%.200s\" is read-only", name);
4993 return -1;
4994 }
4995 }
4996
4997 /* pyrna_py_to_prop sets its own exceptions */
4998 if (prop) {
4999 if (value == nullptr) {
5000 PyErr_SetString(PyExc_AttributeError, "bpy_struct: del not supported");
5001 return -1;
5002 }
5003 return pyrna_py_to_prop(
5004 &self->ptr.value(), prop, nullptr, value, "bpy_struct: item.attr = val:");
5005 }
5006
5007 return PyObject_GenericSetAttr((PyObject *)self, pyname, value);
5008}
5009
5011{
5012 PyObject *ret;
5013 PointerRNA r_ptr;
5014
5015 /* Include this in case this instance is a subtype of a Python class
5016 * In these instances we may want to return a function or variable provided by the subtype. */
5017 ret = PyList_New(0);
5018
5020 pyrna_dir_members_py(ret, (PyObject *)self);
5021 }
5022
5023 if (RNA_property_type(self->prop) == PROP_COLLECTION) {
5024 if (RNA_property_collection_type_get(&self->ptr.value(), self->prop, &r_ptr)) {
5025 pyrna_dir_members_rna(ret, &r_ptr);
5026 }
5027 }
5028
5029 return ret;
5030}
5031
5032static PyObject *pyrna_prop_array_getattro(BPy_PropertyRNA *self, PyObject *pyname)
5033{
5034 return PyObject_GenericGetAttr((PyObject *)self, pyname);
5035}
5036
5037static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject *pyname)
5038{
5039 const char *name = PyUnicode_AsUTF8(pyname);
5040
5041 if (name == nullptr) {
5042 PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string");
5043 return nullptr;
5044 }
5045 if (name[0] != '_') {
5046 PyObject *ret;
5047 PropertyRNA *prop;
5048 FunctionRNA *func;
5049
5050 PointerRNA r_ptr;
5051 if (RNA_property_collection_type_get(&self->ptr.value(), self->prop, &r_ptr)) {
5052 if ((prop = RNA_struct_find_property(&r_ptr, name))) {
5053 ret = pyrna_prop_to_py(&r_ptr, prop);
5054
5055 return ret;
5056 }
5057 if ((func = RNA_struct_find_function(r_ptr.type, name))) {
5058 PyObject *self_collection = pyrna_struct_CreatePyObject(&r_ptr);
5060 &(reinterpret_cast<BPy_DummyPointerRNA *>(self_collection))->ptr.value(), func);
5061 Py_DECREF(self_collection);
5062
5063 return ret;
5064 }
5065 }
5066 }
5067
5068#if 0
5069 return PyObject_GenericGetAttr((PyObject *)self, pyname);
5070#else
5071 {
5072 /* Could just do this except for 1 awkward case.
5073 * `PyObject_GenericGetAttr((PyObject *)self, pyname);`
5074 * so as to support `bpy.data.libraries.load()` */
5075
5076 PyObject *ret = _PyObject_GenericGetAttrWithDict((PyObject *)self, pyname, nullptr, 1);
5077
5078 /* Check the '_' prefix to avoid inheriting `__call__` and similar. */
5079 if ((ret == nullptr) && (name[0] != '_')) {
5080 /* Since this is least common case, handle it last. */
5081 PointerRNA r_ptr;
5082 if (RNA_property_collection_type_get(&self->ptr.value(), self->prop, &r_ptr)) {
5083 PyObject *cls = pyrna_struct_Subtype(&r_ptr);
5084 ret = _PyObject_GenericGetAttrWithDict(cls, pyname, nullptr, 1);
5085 Py_DECREF(cls);
5086
5087 if (ret != nullptr) {
5088 if (Py_TYPE(ret) == &PyMethodDescr_Type) {
5089 PyMethodDef *m = ((PyMethodDescrObject *)ret)->d_method;
5090 /* TODO: #METH_CLASS */
5091 if (m->ml_flags & METH_STATIC) {
5092 /* Keep 'ret' as-is. */
5093 }
5094 else {
5095 Py_DECREF(ret);
5096 ret = PyCMethod_New(m, (PyObject *)self, nullptr, nullptr);
5097 }
5098 }
5099 }
5100 }
5101 }
5102
5103 if (ret == nullptr) {
5104 PyErr_Format(
5105 PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" not found", name);
5106 }
5107
5108 return ret;
5109 }
5110#endif
5111}
5112
5113/* --------------- setattr------------------------------------------- */
5114static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pyname, PyObject *value)
5115{
5116 const char *name = PyUnicode_AsUTF8(pyname);
5117 PropertyRNA *prop;
5118 PointerRNA r_ptr;
5119
5120#ifdef USE_PEDANTIC_WRITE
5121 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), pyname)) {
5122 return -1;
5123 }
5124#endif /* USE_PEDANTIC_WRITE */
5125
5126 if (name == nullptr) {
5127 PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string");
5128 return -1;
5129 }
5130 if (value == nullptr) {
5131 PyErr_SetString(PyExc_AttributeError, "bpy_prop: del not supported");
5132 return -1;
5133 }
5134 if (RNA_property_collection_type_get(&self->ptr.value(), self->prop, &r_ptr)) {
5135 if ((prop = RNA_struct_find_property(&r_ptr, name))) {
5136 /* pyrna_py_to_prop sets its own exceptions. */
5137 return pyrna_py_to_prop(
5138 &r_ptr, prop, nullptr, value, "BPy_PropertyRNA - Attribute (setattr):");
5139 }
5140 }
5141
5142 PyErr_Format(PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" not found", name);
5143 return -1;
5144}
5145
5150 /* Wrap. */
5151 pyrna_prop_collection_idprop_add_doc,
5152 ".. method:: add()\n"
5153 "\n"
5154 " This is a function to add a new item to a collection.\n"
5155 "\n"
5156 " :return: A newly created item.\n"
5157 " :rtype: Any\n");
5159{
5160 PointerRNA r_ptr;
5161
5162#ifdef USE_PEDANTIC_WRITE
5163 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), nullptr)) {
5164 return nullptr;
5165 }
5166#endif /* USE_PEDANTIC_WRITE */
5167
5168 RNA_property_collection_add(&self->ptr.value(), self->prop, &r_ptr);
5169 if (!r_ptr.data) {
5170 PyErr_SetString(PyExc_TypeError,
5171 "bpy_prop_collection.add(): not supported for this collection");
5172 return nullptr;
5173 }
5174
5175 return pyrna_struct_CreatePyObject(&r_ptr);
5176}
5177
5179 /* Wrap. */
5180 pyrna_prop_collection_idprop_remove_doc,
5181 ".. method:: remove(index)\n"
5182 "\n"
5183 " This is a function to remove an item from a collection.\n"
5184 "\n"
5185 " :arg index: Index of the item to be removed.\n"
5186 " :type index: int\n");
5188{
5189 const int key = PyLong_AsLong(value);
5190
5191#ifdef USE_PEDANTIC_WRITE
5192 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), nullptr)) {
5193 return nullptr;
5194 }
5195#endif /* USE_PEDANTIC_WRITE */
5196
5197 if (key == -1 && PyErr_Occurred()) {
5198 PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument");
5199 return nullptr;
5200 }
5201
5202 if (!RNA_property_collection_remove(&self->ptr.value(), self->prop, key)) {
5203 PyErr_SetString(PyExc_TypeError,
5204 "bpy_prop_collection.remove() not supported for this collection");
5205 return nullptr;
5206 }
5207
5208 Py_RETURN_NONE;
5209}
5210
5212 /* Wrap. */
5213 pyrna_prop_collection_idprop_clear_doc,
5214 ".. method:: clear()\n"
5215 "\n"
5216 " This is a function to remove all items from a collection.\n");
5218{
5219#ifdef USE_PEDANTIC_WRITE
5220 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), nullptr)) {
5221 return nullptr;
5222 }
5223#endif /* USE_PEDANTIC_WRITE */
5224
5225 RNA_property_collection_clear(&self->ptr.value(), self->prop);
5226
5227 Py_RETURN_NONE;
5228}
5229
5231 /* Wrap. */
5232 pyrna_prop_collection_idprop_move_doc,
5233 ".. method:: move(src_index, dst_index)\n"
5234 "\n"
5235 " This is a function to move an item in a collection.\n"
5236 "\n"
5237 " :arg src_index: Source item index.\n"
5238 " :type src_index: int\n"
5239 " :arg dst_index: Destination item index.\n"
5240 " :type dst_index: int\n");
5242{
5243 int key = 0, pos = 0;
5244
5245#ifdef USE_PEDANTIC_WRITE
5246 if (rna_disallow_writes && rna_id_write_error(&self->ptr.value(), nullptr)) {
5247 return nullptr;
5248 }
5249#endif /* USE_PEDANTIC_WRITE */
5250
5251 if (!PyArg_ParseTuple(args, "ii", &key, &pos)) {
5252 PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move(): expected two ints as arguments");
5253 return nullptr;
5254 }
5255
5256 if (!RNA_property_collection_move(&self->ptr.value(), self->prop, key, pos)) {
5257 PyErr_SetString(PyExc_TypeError,
5258 "bpy_prop_collection.move() not supported for this collection");
5259 return nullptr;
5260 }
5261
5262 Py_RETURN_NONE;
5263}
5264
5266 /* Wrap. */
5267 pyrna_struct_get_id_data_doc,
5268 "The :class:`bpy.types.ID` object this data-block is from or None, "
5269 "(not available for all data types)\n"
5270 "\n"
5271 ":type: :class:`bpy.types.ID`, (readonly)\n");
5272static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self, void * /*closure*/)
5273{
5274 /* Used for struct and pointer since both have a ptr. */
5275 if (self->ptr->owner_id) {
5276 PointerRNA id_ptr = RNA_id_pointer_create((ID *)self->ptr->owner_id);
5277 return pyrna_struct_CreatePyObject(&id_ptr);
5278 }
5279
5280 Py_RETURN_NONE;
5281}
5282
5284 /* Wrap. */
5285 pyrna_struct_get_data_doc,
5286 "The data this property is using, *type* :class:`bpy.types.bpy_struct`");
5287static PyObject *pyrna_struct_get_data(BPy_DummyPointerRNA *self, void * /*closure*/)
5288{
5289 return pyrna_struct_CreatePyObject(&self->ptr.value());
5290}
5291
5293 /* Wrap. */
5294 pyrna_struct_get_rna_type_doc,
5295 "The property type for introspection.");
5296static PyObject *pyrna_struct_get_rna_type(BPy_PropertyRNA *self, void * /*closure*/)
5297{
5298 PointerRNA tptr = RNA_pointer_create_discrete(nullptr, &RNA_Property, self->prop);
5299 return pyrna_struct_Subtype(&tptr);
5300}
5301
5302/*****************************************************************************/
5303/* Python attributes get/set structure: */
5304/*****************************************************************************/
5305
5306static PyGetSetDef pyrna_prop_getseters[] = {
5307 {"id_data",
5309 (setter) nullptr,
5310 pyrna_struct_get_id_data_doc,
5311 nullptr},
5312 {"data", (getter)pyrna_struct_get_data, (setter) nullptr, pyrna_struct_get_data_doc, nullptr},
5313 {"rna_type",
5315 (setter) nullptr,
5316 pyrna_struct_get_rna_type_doc,
5317 nullptr},
5318 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
5319};
5320
5321static PyGetSetDef pyrna_struct_getseters[] = {
5322 {"id_data",
5324 (setter) nullptr,
5325 pyrna_struct_get_id_data_doc,
5326 nullptr},
5327 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
5328};
5329
5330static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *closure);
5331
5332static PyGetSetDef pyrna_func_getseters[] = {
5333 {"__doc__", (getter)pyrna_func_doc_get, (setter) nullptr, nullptr, nullptr},
5334 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
5335};
5336
5338 /* Wrap. */
5339 pyrna_prop_collection_keys_doc,
5340 ".. method:: keys()\n"
5341 "\n"
5342 " Return the identifiers of collection members\n"
5343 " (matching Python's dict.keys() functionality).\n"
5344 "\n"
5345 " :return: the identifiers for each member of this collection.\n"
5346 " :rtype: list[str]\n");
5348{
5349 PyObject *ret = PyList_New(0);
5350
5351 BPy_NamePropAsPyObject_Cache nameprop_cache = {nullptr};
5352 RNA_PROP_BEGIN (&self->ptr.value(), itemptr, self->prop) {
5353 if (PyObject *name_py = pyrna_struct_get_nameprop_as_pyobject(&itemptr, nameprop_cache)) {
5354 PyList_APPEND(ret, name_py);
5355 }
5356 }
5358
5359 return ret;
5360}
5361
5363 /* Wrap. */
5364 pyrna_prop_collection_items_doc,
5365 ".. method:: items()\n"
5366 "\n"
5367 " Return the identifiers of collection members\n"
5368 " (matching Python's dict.items() functionality).\n"
5369 "\n"
5370 " :return: (key, value) pairs for each member of this collection.\n"
5371 " :rtype: list[tuple[str, :class:`bpy.types.bpy_struct`]]\n");
5373{
5374 PyObject *ret = PyList_New(0);
5375 int i = 0;
5376
5377 BPy_NamePropAsPyObject_Cache nameprop_cache = {nullptr};
5378 RNA_PROP_BEGIN (&self->ptr.value(), itemptr, self->prop) {
5379 if (UNLIKELY(itemptr.data == nullptr)) {
5380 continue;
5381 }
5382 /* Add to Python list. */
5383 PyObject *item = PyTuple_New(2);
5384 PyObject *name_py = pyrna_struct_get_nameprop_as_pyobject(&itemptr, nameprop_cache);
5385 /* Strange to use an index `i` when `name_py` is null, better than excluding it's value.
5386 * In practice this should not happen. */
5387 PyTuple_SET_ITEM(item, 0, name_py ? name_py : PyLong_FromLong(i));
5388 PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr));
5389
5390 PyList_APPEND(ret, item);
5391
5392 i++;
5393 }
5395
5396 return ret;
5397}
5398
5400 /* Wrap. */
5401 pyrna_prop_collection_values_doc,
5402 ".. method:: values()\n"
5403 "\n"
5404 " Return the values of collection\n"
5405 " (matching Python's dict.values() functionality).\n"
5406 "\n"
5407 " :return: The members of this collection.\n"
5408 " :rtype: list[:class:`bpy.types.bpy_struct` | None]\n");
5410{
5411 /* Re-use slice. */
5412 return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
5413}
5414
5416 /* Wrap. */
5417 pyrna_struct_get_doc,
5418 ".. method:: get(key, default=None, /)\n"
5419 "\n"
5420 " Returns the value of the custom property assigned to key or default\n"
5421 " when not found (matches Python's dictionary function of the same name).\n"
5422 "\n"
5423 " :arg key: The key associated with the custom property.\n"
5424 " :type key: str\n"
5425 " :arg default: Optional argument for the value to return if\n"
5426 " *key* is not found.\n"
5427 " :type default: Any\n"
5428 " :return: Custom property value or default.\n"
5429 " :rtype: Any\n"
5431static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args)
5432{
5433 IDProperty *group, *idprop;
5434
5435 const char *key;
5436 PyObject *def = Py_None;
5437
5439
5440 if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) {
5441 return nullptr;
5442 }
5443
5444 /* Mostly copied from BPy_IDGroup_Map_GetItem. */
5445 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
5446 PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties");
5447 return nullptr;
5448 }
5449
5450 group = RNA_struct_idprops(&self->ptr.value(), false);
5451 if (group) {
5452 idprop = IDP_GetPropertyFromGroup(group, key);
5453
5454 if (idprop) {
5455 return BPy_IDGroup_WrapData(self->ptr->owner_id, idprop, group);
5456 }
5457 }
5458
5459 return Py_NewRef(def);
5460}
5461
5463 /* Wrap. */
5464 pyrna_struct_pop_doc,
5465 ".. method:: pop(key, default=None, /)\n"
5466 "\n"
5467 " Remove and return the value of the custom property assigned to key or default\n"
5468 " when not found (matches Python's dictionary function of the same name).\n"
5469 "\n"
5470 " :arg key: The key associated with the custom property.\n"
5471 " :type key: str\n"
5472 " :arg default: Optional argument for the value to return if\n"
5473 " *key* is not found.\n"
5474 " :type default: Any\n"
5475 " :return: Custom property value or default.\n"
5476 " :rtype: Any\n"
5478static PyObject *pyrna_struct_pop(BPy_StructRNA *self, PyObject *args)
5479{
5480 IDProperty *group, *idprop;
5481
5482 const char *key;
5483 PyObject *def = nullptr;
5484
5486
5487 if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) {
5488 return nullptr;
5489 }
5490
5491 /* Mostly copied from BPy_IDGroup_Map_GetItem. */
5492 if (RNA_struct_idprops_check(self->ptr->type) == 0) {
5493 PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties");
5494 return nullptr;
5495 }
5496
5497 group = RNA_struct_idprops(&self->ptr.value(), false);
5498 if (group) {
5499 idprop = IDP_GetPropertyFromGroup(group, key);
5500
5501 if (idprop) {
5502 /* Don't use #BPy_IDGroup_WrapData as the id-property is being removed from the ID. */
5503 PyObject *ret = BPy_IDGroup_MapDataToPy(idprop);
5504 /* Internal error. */
5505 if (UNLIKELY(ret == nullptr)) {
5506 return nullptr;
5507 }
5508 IDP_FreeFromGroup(group, idprop);
5509 return ret;
5510 }
5511 }
5512
5513 if (def == nullptr) {
5514 PyErr_SetString(PyExc_KeyError, "key not found");
5515 return nullptr;
5516 }
5517 return Py_NewRef(def);
5518}
5519
5521 /* Wrap. */
5522 pyrna_struct_as_pointer_doc,
5523 ".. method:: as_pointer()\n"
5524 "\n"
5525 " Returns the memory address which holds a pointer to Blender's internal data\n"
5526 "\n"
5527 " :return: int (memory address).\n"
5528 " :rtype: int\n"
5529 "\n"
5530 " .. note:: This is intended only for advanced script writers who need to\n"
5531 " pass blender data to their own C/Python modules.\n");
5533{
5534 return PyLong_FromVoidPtr(self->ptr->data);
5535}
5536
5538 /* Wrap. */
5539 pyrna_prop_collection_get_doc,
5540 ".. method:: get(key, default=None)\n"
5541 "\n"
5542 " Returns the value of the item assigned to key or default when not found\n"
5543 " (matches Python's dictionary function of the same name).\n"
5544 "\n"
5545 " :arg key: The identifier for the collection member.\n"
5546 " :type key: str\n"
5547 " :arg default: Optional argument for the value to return if\n"
5548 " *key* is not found.\n"
5549 " :type default: Any\n");
5550static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args)
5551{
5552 PointerRNA newptr;
5553
5554 PyObject *key_ob;
5555 PyObject *def = Py_None;
5556
5558
5559 if (!PyArg_ParseTuple(args, "O|O:get", &key_ob, &def)) {
5560 return nullptr;
5561 }
5562
5563 if (PyUnicode_Check(key_ob)) {
5564 const char *key = PyUnicode_AsUTF8(key_ob);
5565
5566 if (RNA_property_collection_lookup_string(&self->ptr.value(), self->prop, key, &newptr)) {
5567 return pyrna_struct_CreatePyObject(&newptr);
5568 }
5570 "bpy_prop_collection.get") == -1)
5571 {
5572 return nullptr;
5573 }
5574 }
5575 else if (PyTuple_Check(key_ob)) {
5577 self, key_ob, "bpy_prop_collection.get((id, lib))", false);
5578 if (ret) {
5579 return ret;
5580 }
5581 }
5582 else {
5583 PyErr_Format(PyExc_KeyError,
5584 "bpy_prop_collection.get(key, ...): key must be a string or tuple, not %.200s",
5585 Py_TYPE(key_ob)->tp_name);
5586 }
5587
5588 return Py_NewRef(def);
5589}
5590
5592 /* Wrap. */
5593 pyrna_prop_collection_find_doc,
5594 ".. method:: find(key)\n"
5595 "\n"
5596 " Returns the index of a key in a collection or -1 when not found\n"
5597 " (matches Python's string find function of the same name).\n"
5598 "\n"
5599 " :arg key: The identifier for the collection member.\n"
5600 " :type key: str\n"
5601 " :return: index of the key.\n"
5602 " :rtype: int\n");
5603static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key_ob)
5604{
5605 Py_ssize_t key_len_ssize;
5606 const char *key = PyUnicode_AsUTF8AndSize(key_ob, &key_len_ssize);
5607 const int key_len = int(key_len_ssize); /* Compare with same type. */
5608
5609 char name[256], *name_ptr;
5610 int name_len;
5611 int i = 0;
5612 int index = -1;
5613
5615
5616 RNA_PROP_BEGIN (&self->ptr.value(), itemptr, self->prop) {
5617 name_ptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &name_len);
5618
5619 if (name_ptr) {
5620 if ((key_len == name_len) && memcmp(name_ptr, key, key_len) == 0) {
5621 index = i;
5622 break;
5623 }
5624
5625 if (name != name_ptr) {
5626 MEM_freeN(name_ptr);
5627 }
5628 }
5629
5630 i++;
5631 }
5633
5634 return PyLong_FromLong(index);
5635}
5636
5638 const char *attr,
5639 /* Values to assign. */
5640 RawPropertyType *r_raw_type,
5641 int *r_attr_tot,
5642 bool *r_attr_signed,
5643 bool *r_is_empty)
5644{
5645 PropertyRNA *prop;
5646 bool attr_ok = true;
5647 *r_raw_type = PROP_RAW_UNSET;
5648 *r_attr_tot = 0;
5649 *r_attr_signed = false;
5650 *r_is_empty = true;
5651
5652 /* NOTE: this is fail with zero length lists, so don't let this get called in that case. */
5653 RNA_PROP_BEGIN (&self->ptr.value(), itemptr, self->prop) {
5654 prop = RNA_struct_find_property(&itemptr, attr);
5655 if (prop) {
5656 *r_raw_type = RNA_property_raw_type(prop);
5657 *r_attr_tot = RNA_property_array_length(&itemptr, prop);
5658 *r_attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED);
5659 }
5660 else {
5661 attr_ok = false;
5662 }
5663 *r_is_empty = false;
5664 break;
5665 }
5667
5668 return attr_ok;
5669}
5670
5671/* pyrna_prop_collection_foreach_get/set both use this. */
5673 PyObject *args,
5674 const char *function_name,
5675
5676 /* Values to assign. */
5677 const char **r_attr,
5678 PyObject **r_seq,
5679 int *r_tot,
5680 size_t *r_size,
5681 RawPropertyType *r_raw_type,
5682 int *r_attr_tot,
5683 bool *r_attr_signed)
5684{
5685 *r_size = *r_attr_tot = 0;
5686 *r_attr_signed = false;
5687 *r_raw_type = PROP_RAW_UNSET;
5688
5689 if (!PyArg_ParseTuple(args, "sO:foreach_get/set", r_attr, r_seq)) {
5690 return -1;
5691 }
5692
5693 if (!PySequence_Check(*r_seq) && PyObject_CheckBuffer(*r_seq)) {
5694 PyErr_Format(PyExc_TypeError,
5695 "%s(..) expected second argument to be a sequence or buffer, not a %.200s",
5696 function_name,
5697 Py_TYPE(*r_seq)->tp_name);
5698 return -1;
5699 }
5700
5701 /* TODO: buffer may not be a sequence! array.array() is though. */
5702 *r_tot = PySequence_Size(*r_seq);
5703
5704 if (*r_tot > 0) {
5705#if 0
5706 /* Avoid a full collection count when all that's needed is to check it's empty. */
5707 int array_tot;
5708
5709 if (RNA_property_type(self->prop) == PROP_COLLECTION) {
5710 array_tot = RNA_property_collection_length(&self->ptr.value(), self->prop);
5711 }
5712 else {
5713 array_tot = RNA_property_array_length(&self->ptr.value(), self->prop);
5714 }
5715 if (array_tot == 0) {
5716 PyErr_Format(PyExc_TypeError,
5717 "%s(..) sequence length mismatch given %d, needed 0",
5718 function_name,
5719 *r_tot);
5720 return -1;
5721 }
5722#endif
5723
5724 bool is_empty = false; /* `array_tot == 0`. */
5725 if (!foreach_attr_type(self, *r_attr, r_raw_type, r_attr_tot, r_attr_signed, &is_empty)) {
5726 PyErr_Format(PyExc_AttributeError,
5727 "%s(..) '%.200s.%200s[...]' elements have no attribute '%.200s'",
5728 function_name,
5729 RNA_struct_identifier(self->ptr->type),
5731 *r_attr);
5732 return -1;
5733 }
5734
5735 if (is_empty) {
5736 PyErr_Format(PyExc_TypeError,
5737 "%s(..) sequence length mismatch given %d, needed 0",
5738 function_name,
5739 *r_tot);
5740 return -1;
5741 }
5742
5743 *r_size = RNA_raw_type_sizeof(*r_raw_type);
5744
5745#if 0
5746 /* This size check does not work as the size check is based on the size of the
5747 * first element and elements in the collection/array can have different sizes
5748 * (i.e. for mixed quad/triangle meshes). See for example issue #111117. */
5749
5750 if ((*r_attr_tot) < 1) {
5751 *r_attr_tot = 1;
5752 }
5753
5754 const int target_tot = array_tot * (*r_attr_tot);
5755
5756 /* rna_access.cc - rna_raw_access(...) uses this same method. */
5757 if (target_tot != (*r_tot)) {
5758 PyErr_Format(PyExc_TypeError,
5759 "%s(..) sequence length mismatch given %d, needed %d",
5760 function_name,
5761 *r_tot,
5762 target_tot);
5763 return -1;
5764 }
5765#endif
5766 }
5767
5768 /* Check 'r_attr_tot' otherwise we don't know if any values were set.
5769 * This isn't ideal because it means running on an empty list may
5770 * fail silently when it's not compatible. */
5771 if (*r_size == 0 && *r_attr_tot != 0) {
5772 PyErr_Format(
5773 PyExc_AttributeError, "%s(..): attribute does not support foreach method", function_name);
5774 return -1;
5775 }
5776 return 0;
5777}
5778
5779static bool foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format)
5780{
5781 const char f = format ? *format : 'B'; /* B is assumed when not set */
5782
5783 switch (raw_type) {
5784 case PROP_RAW_INT8:
5785 if (attr_signed) {
5786 return (f == 'b') ? true : false;
5787 }
5788 else {
5789 return (f == 'B') ? true : false;
5790 }
5791 case PROP_RAW_CHAR:
5792 case PROP_RAW_UINT8:
5793 return (f == 'B') ? true : false;
5794 case PROP_RAW_SHORT:
5795 if (attr_signed) {
5796 return (f == 'h') ? true : false;
5797 }
5798 else {
5799 return (f == 'H') ? true : false;
5800 }
5801 case PROP_RAW_UINT16:
5802 return (f == 'H') ? true : false;
5803 case PROP_RAW_INT:
5804 if (attr_signed) {
5805 return (f == 'i') ? true : false;
5806 }
5807 else {
5808 return (f == 'I') ? true : false;
5809 }
5810 case PROP_RAW_BOOLEAN:
5811 return (f == '?') ? true : false;
5812 case PROP_RAW_FLOAT:
5813 return (f == 'f') ? true : false;
5814 case PROP_RAW_DOUBLE:
5815 return (f == 'd') ? true : false;
5816 case PROP_RAW_INT64:
5817 if (attr_signed) {
5818 return (f == 'q') ? true : false;
5819 }
5820 else {
5821 return (f == 'Q') ? true : false;
5822 }
5823 case PROP_RAW_UINT64:
5824 return (f == 'Q') ? true : false;
5825 case PROP_RAW_UNSET:
5826 return false;
5827 }
5828
5829 return false;
5830}
5831
5832static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
5833{
5834 PyObject *item = nullptr;
5835 int i = 0, ok = 0;
5836 bool buffer_is_compat;
5837 void *array = nullptr;
5838
5839 /* Get/set both take the same args currently. */
5840 const char *attr;
5841 PyObject *seq;
5842 int tot, attr_tot;
5843 size_t size;
5844 bool attr_signed;
5845 RawPropertyType raw_type;
5846
5848 args,
5849 set ? "foreach_set" : "foreach_get",
5850 &attr,
5851 &seq,
5852 &tot,
5853 &size,
5854 &raw_type,
5855 &attr_tot,
5856 &attr_signed) == -1)
5857 {
5858 return nullptr;
5859 }
5860
5861 if (tot == 0) {
5862 Py_RETURN_NONE;
5863 }
5864
5865 if (set) { /* Get the array from python. */
5866 buffer_is_compat = false;
5867 if (PyObject_CheckBuffer(seq)) {
5868 Py_buffer buf;
5869 if (PyObject_GetBuffer(seq, &buf, PyBUF_ND | PyBUF_FORMAT) == -1) {
5870 /* Request failed. A `PyExc_BufferError` will have been raised,
5871 * so clear it to silently fall back to accessing as a sequence. */
5872 PyErr_Clear();
5873 }
5874 else {
5875 /* Check if the buffer matches. */
5876
5877 buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format);
5878
5879 if (buffer_is_compat) {
5881 nullptr, &self->ptr.value(), self->prop, attr, buf.buf, raw_type, tot);
5882 }
5883
5884 PyBuffer_Release(&buf);
5885 }
5886 }
5887
5888 /* Could not use the buffer, fall back to sequence. */
5889 if (!buffer_is_compat) {
5890 array = PyMem_Malloc(size * tot);
5891
5892 for (; i < tot; i++) {
5893 item = PySequence_GetItem(seq, i);
5894 switch (raw_type) {
5895 case PROP_RAW_CHAR:
5896 ((char *)array)[i] = char(PyC_Long_AsU8(item));
5897 break;
5898 case PROP_RAW_INT8:
5899 ((int8_t *)array)[i] = PyC_Long_AsI8(item);
5900 break;
5901 case PROP_RAW_UINT8:
5902 ((uint8_t *)array)[i] = PyC_Long_AsU8(item);
5903 break;
5904 case PROP_RAW_SHORT:
5905 ((short *)array)[i] = short(PyC_Long_AsI16(item));
5906 break;
5907 case PROP_RAW_UINT16:
5908 ((uint16_t *)array)[i] = PyC_Long_AsU16(item);
5909 break;
5910 case PROP_RAW_INT:
5911 ((int *)array)[i] = int(PyC_Long_AsI32(item));
5912 break;
5913 case PROP_RAW_BOOLEAN:
5914 ((bool *)array)[i] = bool(PyC_Long_AsBool(item));
5915 break;
5916 case PROP_RAW_FLOAT:
5917 ((float *)array)[i] = float(PyFloat_AsDouble(item));
5918 break;
5919 case PROP_RAW_DOUBLE:
5920 ((double *)array)[i] = PyFloat_AsDouble(item);
5921 break;
5922 case PROP_RAW_INT64:
5923 ((int64_t *)array)[i] = PyC_Long_AsI64(item);
5924 break;
5925 case PROP_RAW_UINT64:
5926 ((uint64_t *)array)[i] = PyC_Long_AsU64(item);
5927 break;
5928 case PROP_RAW_UNSET:
5929 /* Should never happen. */
5930 BLI_assert_msg(0, "Invalid array type - set");
5931 break;
5932 }
5933
5934 Py_DECREF(item);
5935 }
5936
5938 nullptr, &self->ptr.value(), self->prop, attr, array, raw_type, tot);
5939 }
5940 }
5941 else {
5942 buffer_is_compat = false;
5943 if (PyObject_CheckBuffer(seq)) {
5944 Py_buffer buf;
5945 if (PyObject_GetBuffer(seq, &buf, PyBUF_ND | PyBUF_FORMAT) == -1) {
5946 /* Request failed. A `PyExc_BufferError` will have been raised,
5947 * so clear it to silently fall back to accessing as a sequence. */
5948 PyErr_Clear();
5949 }
5950 else {
5951 /* Check if the buffer matches. */
5952
5953 buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format);
5954
5955 if (buffer_is_compat) {
5957 nullptr, &self->ptr.value(), self->prop, attr, buf.buf, raw_type, tot);
5958 }
5959
5960 PyBuffer_Release(&buf);
5961 }
5962 }
5963
5964 /* Could not use the buffer, fall back to sequence. */
5965 if (!buffer_is_compat) {
5966 array = PyMem_Malloc(size * tot);
5967
5969 nullptr, &self->ptr.value(), self->prop, attr, array, raw_type, tot);
5970
5971 if (!ok) {
5972 /* Skip the loop. */
5973 i = tot;
5974 }
5975
5976 for (; i < tot; i++) {
5977
5978 switch (raw_type) {
5979 case PROP_RAW_CHAR:
5980 item = PyLong_FromLong(long(((char *)array)[i]));
5981 break;
5982 case PROP_RAW_INT8:
5983 item = PyLong_FromLong(long(((int8_t *)array)[i]));
5984 break;
5985 case PROP_RAW_UINT8:
5986 item = PyLong_FromLong(long(((uint8_t *)array)[i]));
5987 break;
5988 case PROP_RAW_SHORT:
5989 item = PyLong_FromLong(long(((short *)array)[i]));
5990 break;
5991 case PROP_RAW_UINT16:
5992 item = PyLong_FromLong(long(((uint16_t *)array)[i]));
5993 break;
5994 case PROP_RAW_INT:
5995 item = PyLong_FromLong(long(((int *)array)[i]));
5996 break;
5997 case PROP_RAW_FLOAT:
5998 item = PyFloat_FromDouble(double(((float *)array)[i]));
5999 break;
6000 case PROP_RAW_DOUBLE:
6001 item = PyFloat_FromDouble(((double *)array)[i]);
6002 break;
6003 case PROP_RAW_BOOLEAN:
6004 item = PyBool_FromLong(long(((bool *)array)[i]));
6005 break;
6006 case PROP_RAW_INT64:
6007 item = PyLong_FromLongLong(((int64_t *)array)[i]);
6008 break;
6009 case PROP_RAW_UINT64:
6010 item = PyLong_FromUnsignedLongLong(((uint64_t *)array)[i]);
6011 break;
6012 default: /* PROP_RAW_UNSET */
6013 /* Should never happen. */
6014 BLI_assert_msg(0, "Invalid array type - get");
6015 item = Py_None;
6016 Py_INCREF(item);
6017 break;
6018 }
6019
6020 PySequence_SetItem(seq, i, item);
6021 Py_DECREF(item);
6022 }
6023 }
6024 }
6025
6026 if (array) {
6027 PyMem_Free(array);
6028 }
6029
6030 if (PyErr_Occurred()) {
6031 /* Maybe we could make our own error. */
6032 PyErr_Print();
6033 PyErr_SetString(PyExc_TypeError, "couldn't access the py sequence");
6034 return nullptr;
6035 }
6036 if (!ok) {
6037 PyErr_SetString(PyExc_RuntimeError, "internal error setting the array");
6038 return nullptr;
6039 }
6040
6041 if (set) {
6042 RNA_property_update(BPY_context_get(), &self->ptr.value(), self->prop);
6043 }
6044 Py_RETURN_NONE;
6045}
6046
6048 /* Wrap. */
6049 pyrna_prop_collection_foreach_get_doc,
6050 ".. method:: foreach_get(attr, seq)\n"
6051 "\n"
6052 " This is a function to give fast access to attributes within a collection.\n");
6054{
6056
6057 return foreach_getset(self, args, 0);
6058}
6059
6061 /* Wrap. */
6062 pyrna_prop_collection_foreach_set_doc,
6063 ".. method:: foreach_set(attr, seq)\n"
6064 "\n"
6065 " This is a function to give fast access to attributes within a collection.\n");
6067{
6069
6070 return foreach_getset(self, args, 1);
6071}
6072
6074 PyObject *args,
6075 const bool do_set)
6076{
6077 PyObject *item = nullptr;
6078 Py_ssize_t i, seq_size, size;
6079 void *array = nullptr;
6080 const PropertyType prop_type = RNA_property_type(self->prop);
6081
6082 /* Get/set both take the same args currently. */
6083 PyObject *seq;
6084
6085 if (!ELEM(prop_type, PROP_INT, PROP_FLOAT)) {
6086 PyErr_SetString(PyExc_TypeError, "foreach_get/set available only for int and float");
6087 return nullptr;
6088 }
6089
6090 if (!PyArg_ParseTuple(args, "O:foreach_get/set", &seq)) {
6091 return nullptr;
6092 }
6093
6094 if (!PySequence_Check(seq) && PyObject_CheckBuffer(seq)) {
6095 PyErr_Format(
6096 PyExc_TypeError,
6097 "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s",
6098 Py_TYPE(seq)->tp_name);
6099 return nullptr;
6100 }
6101
6102 /* NOTE: in this case it's important to use the flat-array size and *not* the result of
6103 * `len()`, which uses #pyrna_prop_array_length, see !116457 for details. */
6104 size = RNA_property_array_length(&self->ptr.value(), self->prop);
6105 seq_size = PySequence_Size(seq);
6106
6107 if (size != seq_size) {
6108 PyErr_Format(PyExc_TypeError, "expected sequence size %d, got %d", size, seq_size);
6109 return nullptr;
6110 }
6111
6112 Py_buffer buf;
6113 if (PyObject_GetBuffer(seq, &buf, PyBUF_ND | PyBUF_FORMAT) == -1) {
6114 PyErr_Clear();
6115
6116 switch (prop_type) {
6117 case PROP_INT:
6118 array = PyMem_Malloc(sizeof(int) * size);
6119 if (do_set) {
6120 for (i = 0; i < size; i++) {
6121 item = PySequence_GetItem(seq, i);
6122 ((int *)array)[i] = int(PyLong_AsLong(item));
6123 Py_DECREF(item);
6124 }
6125
6127 &self->ptr.value(), self->prop, static_cast<const int *>(array));
6128 }
6129 else {
6130 RNA_property_int_get_array(&self->ptr.value(), self->prop, static_cast<int *>(array));
6131
6132 for (i = 0; i < size; i++) {
6133 item = PyLong_FromLong(long(((int *)array)[i]));
6134 PySequence_SetItem(seq, i, item);
6135 Py_DECREF(item);
6136 }
6137 }
6138
6139 break;
6140 case PROP_FLOAT:
6141 array = PyMem_Malloc(sizeof(float) * size);
6142 if (do_set) {
6143 for (i = 0; i < size; i++) {
6144 item = PySequence_GetItem(seq, i);
6145 ((float *)array)[i] = float(PyFloat_AsDouble(item));
6146 Py_DECREF(item);
6147 }
6148
6150 &self->ptr.value(), self->prop, static_cast<const float *>(array));
6151 }
6152 else {
6154 &self->ptr.value(), self->prop, static_cast<float *>(array));
6155
6156 for (i = 0; i < size; i++) {
6157 item = PyFloat_FromDouble(double(((float *)array)[i]));
6158 PySequence_SetItem(seq, i, item);
6159 Py_DECREF(item);
6160 }
6161 }
6162 break;
6163 case PROP_BOOLEAN:
6164 case PROP_STRING:
6165 case PROP_ENUM:
6166 case PROP_POINTER:
6167 case PROP_COLLECTION:
6168 /* Should never happen. */
6170 break;
6171 }
6172
6173 PyMem_Free(array);
6174
6175 if (PyErr_Occurred()) {
6176 /* Maybe we could make our own error. */
6177 PyErr_Print();
6178 PyErr_SetString(PyExc_TypeError, "couldn't access the py sequence");
6179 return nullptr;
6180 }
6181 }
6182 else {
6183 const char f = buf.format ? buf.format[0] : 0;
6184 if ((prop_type == PROP_INT && (buf.itemsize != sizeof(int) || !ELEM(f, 'l', 'i'))) ||
6185 (prop_type == PROP_FLOAT && (buf.itemsize != sizeof(float) || f != 'f')))
6186 {
6187 PyBuffer_Release(&buf);
6188 PyErr_Format(PyExc_TypeError, "incorrect sequence item type: %s", buf.format);
6189 return nullptr;
6190 }
6191
6192 switch (prop_type) {
6193 case PROP_INT:
6194 if (do_set) {
6196 &self->ptr.value(), self->prop, static_cast<const int *>(buf.buf));
6197 }
6198 else {
6199 RNA_property_int_get_array(&self->ptr.value(), self->prop, static_cast<int *>(buf.buf));
6200 }
6201 break;
6202 case PROP_FLOAT:
6203 if (do_set) {
6205 &self->ptr.value(), self->prop, static_cast<const float *>(buf.buf));
6206 }
6207 else {
6209 &self->ptr.value(), self->prop, static_cast<float *>(buf.buf));
6210 }
6211 break;
6212 case PROP_BOOLEAN:
6213 case PROP_STRING:
6214 case PROP_ENUM:
6215 case PROP_POINTER:
6216 case PROP_COLLECTION:
6217 /* Should never happen. */
6219 break;
6220 }
6221
6222 PyBuffer_Release(&buf);
6223 }
6224
6225 Py_RETURN_NONE;
6226}
6227
6229 /* Wrap. */
6230 pyrna_prop_array_foreach_get_doc,
6231 ".. method:: foreach_get(seq)\n"
6232 "\n"
6233 " This is a function to give fast access to array data.\n");
6235{
6237
6238 return pyprop_array_foreach_getset(self, args, false);
6239}
6240
6242 /* Wrap. */
6243 pyrna_prop_array_foreach_set_doc,
6244 ".. method:: foreach_set(seq)\n"
6245 "\n"
6246 " This is a function to give fast access to array data.\n");
6248{
6250
6251 return pyprop_array_foreach_getset(self, args, true);
6252}
6253
6254/* A bit of a kludge, make a list out of a collection or array,
6255 * then return the list's iter function, not especially fast, but convenient for now. */
6257{
6258 /* Try get values from a collection. */
6259 PyObject *ret;
6260 PyObject *iter = nullptr;
6261 int len;
6262
6264
6266 ret = pyrna_prop_array_subscript_slice(self, &self->ptr.value(), self->prop, 0, len, len);
6267
6268 /* we know this is a list so no need to PyIter_Check
6269 * otherwise it could be nullptr (unlikely) if conversion failed */
6270 if (ret) {
6271 iter = PyObject_GetIter(ret);
6272 Py_DECREF(ret);
6273 }
6274
6275 return iter;
6276}
6277
6278static PyObject *pyrna_prop_collection_iter(PyObject *self);
6279
6280#ifndef USE_PYRNA_ITER
6281static PyObject *pyrna_prop_collection_iter(PyObject *self)
6282{
6283 BPy_PropertyRNA *self_property = reinterpret_cast<BPy_PropertyRNA *>(self);
6284
6285 /* Try get values from a collection. */
6286 PyObject *ret;
6287 PyObject *iter = nullptr;
6288 ret = pyrna_prop_collection_values(self_property);
6289
6290 /* we know this is a list so no need to PyIter_Check
6291 * otherwise it could be nullptr (unlikely) if conversion failed */
6292 if (ret) {
6293 iter = PyObject_GetIter(ret);
6294 Py_DECREF(ret);
6295 }
6296
6297 return iter;
6298}
6299#endif /* # !USE_PYRNA_ITER */
6300
6301#ifdef __GNUC__
6302# ifdef __clang__
6303# pragma clang diagnostic push
6304# pragma clang diagnostic ignored "-Wcast-function-type"
6305# else
6306# pragma GCC diagnostic push
6307# pragma GCC diagnostic ignored "-Wcast-function-type"
6308# endif
6309#endif
6310
6311static PyMethodDef pyrna_struct_methods[] = {
6312
6313 /* Only for PointerRNA's with ID'props. */
6314 {"keys", (PyCFunction)pyrna_struct_keys, METH_NOARGS, pyrna_struct_keys_doc},
6315 {"values", (PyCFunction)pyrna_struct_values, METH_NOARGS, pyrna_struct_values_doc},
6316 {"items", (PyCFunction)pyrna_struct_items, METH_NOARGS, pyrna_struct_items_doc},
6317
6318 {"get", (PyCFunction)pyrna_struct_get, METH_VARARGS, pyrna_struct_get_doc},
6319 {"pop", (PyCFunction)pyrna_struct_pop, METH_VARARGS, pyrna_struct_pop_doc},
6320
6321 {"as_pointer", (PyCFunction)pyrna_struct_as_pointer, METH_NOARGS, pyrna_struct_as_pointer_doc},
6322
6323 /* `bpy_rna_anim.cc` */
6324 {"keyframe_insert",
6325 (PyCFunction)pyrna_struct_keyframe_insert,
6326 METH_VARARGS | METH_KEYWORDS,
6328 {"keyframe_delete",
6329 (PyCFunction)pyrna_struct_keyframe_delete,
6330 METH_VARARGS | METH_KEYWORDS,
6332 {"driver_add",
6333 (PyCFunction)pyrna_struct_driver_add,
6334 METH_VARARGS,
6336 {"driver_remove",
6337 (PyCFunction)pyrna_struct_driver_remove,
6338 METH_VARARGS,
6340
6341 {"is_property_set",
6342 (PyCFunction)pyrna_struct_is_property_set,
6343 METH_VARARGS | METH_KEYWORDS,
6344 pyrna_struct_is_property_set_doc},
6345 {"property_unset",
6346 (PyCFunction)pyrna_struct_property_unset,
6347 METH_VARARGS,
6348 pyrna_struct_property_unset_doc},
6349 {"is_property_hidden",
6351 METH_VARARGS,
6352 pyrna_struct_is_property_hidden_doc},
6353 {"is_property_readonly",
6355 METH_VARARGS,
6356 pyrna_struct_is_property_readonly_doc},
6357 {"is_property_overridable_library",
6359 METH_VARARGS,
6360 pyrna_struct_is_property_overridable_library_doc},
6361 {"property_overridable_library_set",
6363 METH_VARARGS,
6364 pyrna_struct_property_overridable_library_set_doc},
6365 {"path_resolve",
6366 (PyCFunction)pyrna_struct_path_resolve,
6367 METH_VARARGS,
6368 pyrna_struct_path_resolve_doc},
6369 {"path_from_id",
6370 (PyCFunction)pyrna_struct_path_from_id,
6371 METH_VARARGS,
6372 pyrna_struct_path_from_id_doc},
6373 {"path_from_module",
6374 (PyCFunction)pyrna_struct_path_from_module,
6375 METH_VARARGS,
6376 pyrna_struct_path_from_module_doc},
6377 {"type_recast",
6378 (PyCFunction)pyrna_struct_type_recast,
6379 METH_NOARGS,
6380 pyrna_struct_type_recast_doc},
6381 {"bl_rna_get_subclass_py",
6383 METH_VARARGS | METH_CLASS,
6384 pyrna_struct_bl_rna_get_subclass_py_doc},
6385 {"bl_rna_get_subclass",
6387 METH_VARARGS | METH_CLASS,
6388 pyrna_struct_bl_rna_get_subclass_doc},
6389 {"rna_ancestors",
6390 (PyCFunction)pyrna_struct_get_ancestors,
6391 METH_NOARGS,
6392 pyrna_struct_get_ancestors_doc},
6393 {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, nullptr},
6394 {"id_properties_ensure",
6396 METH_NOARGS,
6397 pyrna_struct_id_properties_ensure_doc},
6398 {"id_properties_clear",
6400 METH_NOARGS,
6401 pyrna_struct_id_properties_clear_doc},
6402 {"id_properties_ui",
6403 (PyCFunction)pyrna_struct_id_properties_ui,
6404 METH_VARARGS,
6405 pyrna_struct_id_properties_ui_doc},
6406
6407/* experimental */
6408/* unused for now */
6409#if 0
6410 {"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, nullptr},
6411 {"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, nullptr},
6412
6413 {"callback_add",
6414 (PyCFunction)pyrna_callback_classmethod_add,
6415 METH_VARARGS | METH_CLASS,
6416 nullptr},
6417 {"callback_remove",
6419 METH_VARARGS | METH_CLASS,
6420 nullptr},
6421#endif
6422 {nullptr, nullptr, 0, nullptr},
6423};
6424
6425static PyMethodDef pyrna_prop_methods[] = {
6426 {"path_from_id",
6427 (PyCFunction)pyrna_prop_path_from_id,
6428 METH_NOARGS,
6429 pyrna_prop_path_from_id_doc},
6430 {"path_from_module",
6431 (PyCFunction)pyrna_prop_path_from_module,
6432 METH_NOARGS,
6433 pyrna_prop_path_from_module_doc},
6434 {"as_bytes", (PyCFunction)pyrna_prop_as_bytes, METH_NOARGS, pyrna_prop_as_bytes_doc},
6435 {"update", (PyCFunction)pyrna_prop_update, METH_NOARGS, pyrna_prop_update_doc},
6436 {"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, nullptr},
6437 {nullptr, nullptr, 0, nullptr},
6438};
6439
6440static PyMethodDef pyrna_prop_array_methods[] = {
6441 {"foreach_get",
6442 (PyCFunction)pyrna_prop_array_foreach_get,
6443 METH_VARARGS,
6444 pyrna_prop_array_foreach_get_doc},
6445 {"foreach_set",
6446 (PyCFunction)pyrna_prop_array_foreach_set,
6447 METH_VARARGS,
6448 pyrna_prop_array_foreach_set_doc},
6449
6450 {nullptr, nullptr, 0, nullptr},
6451};
6452
6453static PyMethodDef pyrna_prop_collection_methods[] = {
6454 {"foreach_get",
6456 METH_VARARGS,
6457 pyrna_prop_collection_foreach_get_doc},
6458 {"foreach_set",
6460 METH_VARARGS,
6461 pyrna_prop_collection_foreach_set_doc},
6462
6463 {"keys", (PyCFunction)pyrna_prop_collection_keys, METH_NOARGS, pyrna_prop_collection_keys_doc},
6464 {"items",
6465 (PyCFunction)pyrna_prop_collection_items,
6466 METH_NOARGS,
6467 pyrna_prop_collection_items_doc},
6468 {"values",
6469 (PyCFunction)pyrna_prop_collection_values,
6470 METH_NOARGS,
6471 pyrna_prop_collection_values_doc},
6472
6473 {"get", (PyCFunction)pyrna_prop_collection_get, METH_VARARGS, pyrna_prop_collection_get_doc},
6474 {"find", (PyCFunction)pyrna_prop_collection_find, METH_O, pyrna_prop_collection_find_doc},
6475 {nullptr, nullptr, 0, nullptr},
6476};
6477
6479 {"add",
6481 METH_NOARGS,
6482 pyrna_prop_collection_idprop_add_doc},
6483 {"remove",
6485 METH_O,
6486 pyrna_prop_collection_idprop_remove_doc},
6487 {"clear",
6489 METH_NOARGS,
6490 pyrna_prop_collection_idprop_clear_doc},
6491 {"move",
6493 METH_VARARGS,
6494 pyrna_prop_collection_idprop_move_doc},
6495 {nullptr, nullptr, 0, nullptr},
6496};
6497
6498#ifdef __GNUC__
6499# ifdef __clang__
6500# pragma clang diagnostic pop
6501# else
6502# pragma GCC diagnostic pop
6503# endif
6504#endif
6505
6506static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
6507{
6508 PyObject *ret;
6509 const int type = RNA_property_type(prop);
6510 const int flag = RNA_property_flag(prop);
6511 const int flag_parameter = RNA_parameter_flag(prop);
6512
6513 if (RNA_property_array_check(prop)) {
6514 int a, len;
6515
6516 if (flag & PROP_DYNAMIC) {
6517 ParameterDynAlloc *data_alloc = static_cast<ParameterDynAlloc *>(data);
6518 len = data_alloc->array_tot;
6519 data = data_alloc->array;
6520 }
6521 else {
6523 }
6524
6525 /* Resolve the array from a new Python type. */
6526
6527 /* TODO(Kazanbas): make multi-dimensional sequences here. */
6528
6529 switch (type) {
6530 case PROP_BOOLEAN:
6531 ret = PyTuple_New(len);
6532 for (a = 0; a < len; a++) {
6533 PyTuple_SET_ITEM(ret, a, PyBool_FromLong(((bool *)data)[a]));
6534 }
6535 break;
6536 case PROP_INT:
6537 ret = PyTuple_New(len);
6538 for (a = 0; a < len; a++) {
6539 PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a]));
6540 }
6541 break;
6542 case PROP_FLOAT:
6543 switch (RNA_property_subtype(prop)) {
6544#ifdef USE_MATHUTILS
6546 ret = Vector_CreatePyObject(static_cast<const float *>(data), len, nullptr);
6547 break;
6548 case PROP_MATRIX:
6549 if (len == 16) {
6550 ret = Matrix_CreatePyObject(static_cast<const float *>(data), 4, 4, nullptr);
6551 break;
6552 }
6553 else if (len == 9) {
6554 ret = Matrix_CreatePyObject(static_cast<const float *>(data), 3, 3, nullptr);
6555 break;
6556 }
6558#endif
6559 default:
6560 ret = PyTuple_New(len);
6561 for (a = 0; a < len; a++) {
6562 PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble(((float *)data)[a]));
6563 }
6564 break;
6565 }
6566 break;
6567 default:
6568 PyErr_Format(
6569 PyExc_TypeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type);
6570 ret = nullptr;
6571 break;
6572 }
6573 }
6574 else {
6575 /* See if we can coerce into a python type - PropertyType. */
6576 switch (type) {
6577 case PROP_BOOLEAN:
6578 ret = PyBool_FromLong(*(bool *)data);
6579 break;
6580 case PROP_INT:
6581 ret = PyLong_FromLong(*(int *)data);
6582 break;
6583 case PROP_FLOAT:
6584 ret = PyFloat_FromDouble(*(float *)data);
6585 break;
6586 case PROP_STRING: {
6587 const char *data_ch;
6588 const int subtype = RNA_property_subtype(prop);
6589 size_t data_ch_len;
6590
6591 if (flag & PROP_DYNAMIC) {
6592 ParameterDynAlloc *data_alloc = static_cast<ParameterDynAlloc *>(data);
6593 data_ch = static_cast<const char *>(data_alloc->array);
6594 data_ch_len = data_alloc->array_tot;
6595 BLI_assert((data_ch == nullptr) || strlen(data_ch) == data_ch_len);
6596 }
6597 else {
6598 data_ch = (flag & PROP_THICK_WRAP) ? (char *)data : *(char **)data;
6599 data_ch_len = data_ch ? strlen(data_ch) : 0;
6600 }
6601
6602 if (UNLIKELY(data_ch == nullptr)) {
6604 ret = Py_None;
6605 Py_INCREF(ret);
6606 }
6607#ifdef USE_STRING_COERCE
6608 else if (subtype == PROP_BYTESTRING) {
6609 ret = PyBytes_FromStringAndSize(data_ch, data_ch_len);
6610 }
6611 else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
6612 ret = PyC_UnicodeFromBytesAndSize(data_ch, data_ch_len);
6613 }
6614 else {
6615 ret = PyUnicode_FromStringAndSize(data_ch, data_ch_len);
6616 }
6617#else
6618 else if (subtype == PROP_BYTESTRING) {
6619 ret = PyBytes_FromString(buf);
6620 }
6621 else {
6622 ret = PyUnicode_FromString(data_ch);
6623 }
6624#endif
6625
6626 break;
6627 }
6628 case PROP_ENUM: {
6629 ret = pyrna_enum_to_py(ptr, prop, *(int *)data);
6630 break;
6631 }
6632 case PROP_POINTER: {
6633 PointerRNA newptr;
6634 PointerRNA *newptr_p = nullptr;
6635 StructRNA *ptype = RNA_property_pointer_type(ptr, prop);
6636
6637 if (flag_parameter & PARM_RNAPTR) {
6638 if (flag & PROP_THICK_WRAP) {
6639 /* `data` points to a PointerRNA. */
6640 newptr_p = static_cast<PointerRNA *>(data);
6641 }
6642 else {
6643 /* `data` points to a pointer to a PointerRNA. */
6644 newptr_p = *reinterpret_cast<PointerRNA **>(data);
6645 }
6646 }
6647 else {
6648 if (RNA_struct_is_ID(ptype)) {
6649 newptr = RNA_id_pointer_create(static_cast<ID *>(*(void **)data));
6650 }
6651 else {
6652 /* NOTE: this is taken from the function's ID pointer
6653 * and will break if a function returns a pointer from
6654 * another ID block, watch this! - it should at least be
6655 * easy to debug since they are all ID's */
6656 newptr = RNA_pointer_create_discrete(ptr->owner_id, ptype, *(void **)data);
6657 }
6658 newptr_p = &newptr;
6659 }
6660
6661 if (newptr_p->data) {
6662 ret = pyrna_struct_CreatePyObject(newptr_p);
6663 }
6664 else {
6665 ret = Py_None;
6666 Py_INCREF(ret);
6667 }
6668 break;
6669 }
6670 case PROP_COLLECTION: {
6672 ret = PyList_New(0);
6673 for (PointerRNA &ptr_iter : lb->items) {
6674 PyList_APPEND(ret, pyrna_struct_CreatePyObject(&ptr_iter));
6675 }
6676 break;
6677 }
6678 default:
6679 PyErr_Format(PyExc_TypeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type);
6680 ret = nullptr;
6681 break;
6682 }
6683 }
6684
6685 return ret;
6686}
6687
6688inline static PyObject *kwnames_get_item_string(PyObject *const *args,
6689 Py_ssize_t nargs,
6690 PyObject *kwnames,
6691 Py_ssize_t nkw,
6692 const char *parm_name)
6693{
6694 const Py_ssize_t parm_name_len = strlen(parm_name);
6695
6696 for (Py_ssize_t i = 0; i < nkw; i++) {
6697 PyObject *key = PyTuple_GET_ITEM(kwnames, i); /* Borrow reference. */
6698 if (PyUnicode_Check(key)) {
6699 Py_ssize_t key_buf_len;
6700 const char *key_buf = PyUnicode_AsUTF8AndSize(key, &key_buf_len);
6701 if ((parm_name_len == key_buf_len) && (memcmp(parm_name, key_buf, parm_name_len) == 0)) {
6702 return args[nargs + i]; /* Borrow reference. */
6703 }
6704 }
6705 }
6706
6707 return nullptr;
6708}
6709
6714 PropertyRNA *parm,
6715 const int parm_index,
6716 char *error,
6717 const size_t error_size)
6718{
6719 PointerRNA *self_ptr = &self->ptr.value();
6720 FunctionRNA *self_func = self->func;
6721 if (parm_index == -1) {
6723 error_size,
6724 "%.200s.%.200s(): error with keyword argument \"%.200s\" - ",
6725 RNA_struct_identifier(self_ptr->type),
6726 RNA_function_identifier(self_func),
6728 }
6729 else {
6731 error_size,
6732 "%.200s.%.200s(): error with argument %d, \"%.200s\" - ",
6733 RNA_struct_identifier(self_ptr->type),
6734 RNA_function_identifier(self_func),
6735 parm_index + 1,
6737 }
6738}
6739
6745static PyObject *pyrna_func_vectorcall(PyObject *callable,
6746 PyObject *const *args,
6747 size_t nargsf,
6748 PyObject *kwnames)
6749{
6750 /* NOTE: both BPy_StructRNA and BPy_PropertyRNA can be used here. */
6751 BPy_FunctionRNA *self = reinterpret_cast<BPy_FunctionRNA *>(callable);
6752 PointerRNA *self_ptr = &self->ptr.value();
6753 FunctionRNA *self_func = self->func;
6754
6755 ParameterList parms;
6756 ParameterIterator iter;
6757 PropertyRNA *parm;
6758 PyObject *ret, *item;
6759 int i, parms_len, ret_len, flag_parameter, err = 0, kw_tot = 0;
6760 bool kw_arg;
6761
6762 PropertyRNA *pret_single = nullptr;
6763 void *retdata_single = nullptr;
6764
6765 /* enable this so all strings are copied and freed after calling.
6766 * this exposes bugs where the pointer to the string is held and re-used */
6767 // #define DEBUG_STRING_FREE
6768
6769#ifdef DEBUG_STRING_FREE
6770 PyObject *string_free_ls = PyList_New(0);
6771#endif
6772
6773 /* Should never happen, but it does in rare cases. */
6774 BLI_assert(self_ptr != nullptr);
6775
6776 if (self_ptr == nullptr) {
6777 PyErr_SetString(PyExc_RuntimeError,
6778 "RNA functions internal RNA pointer is null, this is a bug. aborting");
6779 return nullptr;
6780 }
6781
6782 if (self_func == nullptr) {
6783 PyErr_Format(
6784 PyExc_RuntimeError,
6785 "%.200s.<unknown>(): RNA function internal function is null, this is a bug. aborting",
6786 RNA_struct_identifier(self_ptr->type));
6787 return nullptr;
6788 }
6789
6790/* For testing. */
6791#if 0
6792 {
6793 const char *fn;
6794 int lineno;
6795 PyC_FileAndNum(&fn, &lineno);
6796 printf("pyrna_func_call > %.200s.%.200s : %.200s:%d\n",
6797 RNA_struct_identifier(self_ptr->type),
6798 RNA_function_identifier(self_func),
6799 fn,
6800 lineno);
6801 }
6802#endif
6803
6804 /* include the ID pointer for pyrna_param_to_py() so we can include the
6805 * ID pointer on return values, this only works when returned values have
6806 * the same ID as the functions. */
6807 PointerRNA funcptr = RNA_pointer_create_discrete(self_ptr->owner_id, &RNA_Function, self_func);
6808
6809 const Py_ssize_t pyargs_len = PyVectorcall_NARGS(nargsf);
6810 const Py_ssize_t pykw_len = kwnames ? PyTuple_GET_SIZE(kwnames) : 0;
6811
6812 RNA_parameter_list_create(&parms, self_ptr, self_func);
6813 RNA_parameter_list_begin(&parms, &iter);
6814 parms_len = RNA_parameter_list_arg_count(&parms);
6815 ret_len = 0;
6816
6817 if (pyargs_len + pykw_len > parms_len) {
6819 PyErr_Format(PyExc_TypeError,
6820 "%.200s.%.200s(): takes at most %d arguments, got %d",
6821 RNA_struct_identifier(self_ptr->type),
6822 RNA_function_identifier(self_func),
6823 parms_len,
6824 pyargs_len + pykw_len);
6825 err = -1;
6826 }
6827
6828 /* Parse function parameters. */
6829 for (i = 0; iter.valid && err == 0; RNA_parameter_list_next(&iter)) {
6830 parm = iter.parm;
6831 flag_parameter = RNA_parameter_flag(parm);
6832 /* Only useful for single argument returns, we'll need another list loop for multiple. */
6833 if (flag_parameter & PARM_OUTPUT) {
6834 ret_len++;
6835 if (pret_single == nullptr) {
6836 pret_single = parm;
6837 retdata_single = iter.data;
6838 }
6839
6840 continue;
6841 }
6842
6843 item = nullptr;
6844
6845 if (i < pyargs_len) {
6846 /* New in 2.8x, optional arguments must be keywords. */
6847 if (UNLIKELY((flag_parameter & PARM_REQUIRED) == 0)) {
6848 PyErr_Format(PyExc_TypeError,
6849 "%.200s.%.200s(): required parameter \"%.200s\" to be a keyword argument!",
6850 RNA_struct_identifier(self_ptr->type),
6851 RNA_function_identifier(self_func),
6853 err = -1;
6854 break;
6855 }
6856
6857 item = args[i];
6858 kw_arg = false;
6859 }
6860 else if (kwnames != nullptr) {
6861 item = kwnames_get_item_string(args,
6862 pyargs_len,
6863 kwnames,
6864 pykw_len,
6865 RNA_property_identifier(parm)); /* Borrow reference. */
6866
6867 if (item) {
6868 kw_tot++; /* Make sure invalid keywords are not given. */
6869 }
6870
6871 kw_arg = true;
6872 }
6873
6874 if (item == nullptr) {
6875 if (flag_parameter & PARM_REQUIRED) {
6876 PyErr_Format(PyExc_TypeError,
6877 "%.200s.%.200s(): required parameter \"%.200s\" not specified",
6878 RNA_struct_identifier(self_ptr->type),
6879 RNA_function_identifier(self_func),
6881 err = -1;
6882 break;
6883 }
6884 /* PyDict_GetItemString won't raise an error. */
6885 }
6886 else {
6887
6888#ifdef DEBUG_STRING_FREE
6889 if (item) {
6890 if (PyUnicode_Check(item)) {
6891 PyList_APPEND(string_free_ls, PyUnicode_FromString(PyUnicode_AsUTF8(item)));
6892 }
6893 }
6894#endif
6895
6896 /* the error generated isn't that useful, so generate it again with a useful prefix
6897 * could also write a function to prepend to error messages */
6898 char error_prefix[512];
6899
6900 err = pyrna_py_to_prop(&funcptr, parm, iter.data, item, "");
6901
6902 if (err != 0) {
6903 PyErr_Clear(); /* Re-raise. */
6904 pyrna_func_error_prefix(self, parm, kw_arg ? -1 : i, error_prefix, sizeof(error_prefix));
6905 pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix);
6906
6907 break;
6908 }
6909 }
6910
6911 i++; /* Current argument. */
6912 }
6913
6915
6916 /* Check if we gave args that don't exist in the function
6917 * Printing the error is slow, but it should only happen when developing.
6918 * The "if" below is quick check to make sure less keyword args were passed than we gave.
6919 * (Don't overwrite the error if we have one,
6920 * otherwise can skip important messages and confuse with args).
6921 */
6922 if (UNLIKELY(err == 0 && kwnames && (pykw_len > kw_tot))) {
6923 DynStr *bad_args = BLI_dynstr_new();
6924 DynStr *good_args = BLI_dynstr_new();
6925
6926 const char *arg_name, *bad_args_str, *good_args_str;
6927 bool found = false, first = true;
6928
6929 for (Py_ssize_t i = 0; i < pykw_len; i++) {
6930 PyObject *key = PyTuple_GET_ITEM(kwnames, i); /* Borrow reference. */
6931
6932 arg_name = PyUnicode_AsUTF8(key);
6933 found = false;
6934
6935 if (arg_name == nullptr)
6936 { /* Unlikely the `arg_name` is not a string, but ignore if it is. */
6937 PyErr_Clear();
6938 }
6939 else {
6940 /* Search for arg_name. */
6941 RNA_parameter_list_begin(&parms, &iter);
6942 for (; iter.valid; RNA_parameter_list_next(&iter)) {
6943 parm = iter.parm;
6944 if (STREQ(arg_name, RNA_property_identifier(parm))) {
6945 found = true;
6946 break;
6947 }
6948 }
6949
6951
6952 if (found == false) {
6953 BLI_dynstr_appendf(bad_args, first ? "%s" : ", %s", arg_name);
6954 first = false;
6955 }
6956 }
6957 }
6958
6959 /* List good args. */
6960 first = true;
6961
6962 RNA_parameter_list_begin(&parms, &iter);
6963 for (; iter.valid; RNA_parameter_list_next(&iter)) {
6964 parm = iter.parm;
6965 if (RNA_parameter_flag(parm) & PARM_OUTPUT) {
6966 continue;
6967 }
6968
6969 BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm));
6970 first = false;
6971 }
6973
6974 bad_args_str = BLI_dynstr_get_cstring(bad_args);
6975 good_args_str = BLI_dynstr_get_cstring(good_args);
6976
6977 PyErr_Format(
6978 PyExc_TypeError,
6979 "%.200s.%.200s(): was called with invalid keyword argument(s) (%s), expected (%s)",
6980 RNA_struct_identifier(self_ptr->type),
6981 RNA_function_identifier(self_func),
6982 bad_args_str,
6983 good_args_str);
6984
6985 BLI_dynstr_free(bad_args);
6986 BLI_dynstr_free(good_args);
6987 MEM_freeN(bad_args_str);
6988 MEM_freeN(good_args_str);
6989
6990 err = -1;
6991 }
6992
6993 ret = nullptr;
6994 if (err == 0) {
6995 /* Call function. */
6996 ReportList reports;
6998
6999 /* No need to print any reports. We will turn errors into Python exceptions, and
7000 * Python API calls should be silent and not print info or warning messages. */
7002 RNA_function_call(C, &reports, self_ptr, self_func, &parms);
7003
7004 err = BPy_reports_to_error(&reports, PyExc_RuntimeError, true);
7005
7006 /* Return value. */
7007 if (err != -1) {
7008 if (ret_len > 0) {
7009 if (ret_len > 1) {
7010 ret = PyTuple_New(ret_len);
7011 i = 0; /* Arg index. */
7012
7013 RNA_parameter_list_begin(&parms, &iter);
7014
7015 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7016 parm = iter.parm;
7017
7018 if (RNA_parameter_flag(parm) & PARM_OUTPUT) {
7019 PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data));
7020 }
7021 }
7022
7024 }
7025 else {
7026 ret = pyrna_param_to_py(&funcptr, pret_single, retdata_single);
7027 }
7028
7029 /* Possible there is an error in conversion. */
7030 if (ret == nullptr) {
7031 err = -1;
7032 }
7033 }
7034 }
7035 }
7036
7037#ifdef DEBUG_STRING_FREE
7038# if 0
7039 if (PyList_GET_SIZE(string_free_ls)) {
7040 printf("%.200s.%.200s(): has %d strings\n",
7041 RNA_struct_identifier(self_ptr->type),
7042 RNA_function_identifier(self_func),
7043 int(PyList_GET_SIZE(string_free_ls)));
7044 }
7045# endif
7046 Py_DECREF(string_free_ls);
7047# undef DEBUG_STRING_FREE
7048#endif
7049
7050 /* Cleanup. */
7053
7054 if (ret) {
7055 return ret;
7056 }
7057
7058 if (err == -1) {
7059 return nullptr;
7060 }
7061
7062 Py_RETURN_NONE;
7063}
7064
7065static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void * /*closure*/)
7066{
7067 PyObject *ret;
7068
7069 std::string args = RNA_function_as_string_keywords(nullptr, self->func, true, true, INT_MAX);
7070
7071 ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s",
7072 RNA_struct_identifier(self->ptr->type),
7074 args.c_str(),
7076
7077 return ret;
7078}
7079
7081 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
7082 /*tp_name*/ "bpy_struct_meta_idprop",
7083 /* NOTE: would be `sizeof(PyTypeObject)`,
7084 * but sub-types of Type must be #PyHeapTypeObject's. */
7085 /*tp_basicsize*/ sizeof(PyHeapTypeObject),
7086 /*tp_itemsize*/ 0,
7087 /*tp_dealloc*/ nullptr,
7088 /*tp_vectorcall_offset*/ 0,
7089 /*tp_getattr*/ nullptr,
7090 /*tp_setattr*/ nullptr,
7091 /*tp_as_async*/ nullptr,
7092 /*tp_repr*/ nullptr,
7093 /*tp_as_number*/ nullptr,
7094 /*tp_as_sequence*/ nullptr,
7095 /*tp_as_mapping*/ nullptr,
7096 /*tp_hash*/ nullptr,
7097 /*tp_call*/ nullptr,
7098 /*tp_str*/ nullptr,
7099 /*tp_getattro*/ nullptr, /* Sub-classed: #pyrna_struct_meta_idprop_getattro. */
7100 /*tp_setattro*/ (setattrofunc)pyrna_struct_meta_idprop_setattro,
7101 /*tp_as_buffer*/ nullptr,
7102 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
7103 /*tp_doc*/ nullptr,
7104 /*tp_traverse*/ nullptr,
7105 /*tp_clear*/ nullptr,
7106 /*tp_richcompare*/ nullptr,
7107 /*tp_weaklistoffset*/ 0,
7108 /*tp_iter*/ nullptr,
7109 /*tp_iternext*/ nullptr,
7110 /*tp_methods*/ nullptr,
7111 /*tp_members*/ nullptr,
7112 /*tp_getset*/ nullptr,
7113#if defined(_MSC_VER)
7114 /*tp_base*/ nullptr, /* Defer assignment. */
7115#else
7116 /*tp_base*/ &PyType_Type,
7117#endif
7118 /*tp_dict*/ nullptr,
7119 /*tp_descr_get*/ nullptr,
7120 /*tp_descr_set*/ nullptr,
7121 /*tp_dictoffset*/ 0,
7122 /*tp_init*/ nullptr,
7123 /*tp_alloc*/ nullptr,
7124 /*tp_new*/ nullptr,
7125 /*tp_free*/ nullptr,
7126 /*tp_is_gc*/ nullptr,
7127 /*tp_bases*/ nullptr,
7128 /*tp_mro*/ nullptr,
7129 /*tp_cache*/ nullptr,
7130 /*tp_subclasses*/ nullptr,
7131 /*tp_weaklist*/ nullptr,
7132 /*tp_del*/ nullptr,
7133 /*tp_version_tag*/ 0,
7134 /*tp_finalize*/ nullptr,
7135 /*tp_vectorcall*/ nullptr,
7136};
7137
7138/*-----------------------BPy_StructRNA method def------------------------------*/
7139
7140/* -------------------------------------------------------------------- */
7167
7168static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject * /*kwds*/);
7169static int pyrna_struct_init(PyObject *self, PyObject *args, PyObject * /*kwds*/);
7170static void pyrna_struct_dealloc(PyObject *self);
7171
7172PyTypeObject pyrna_struct_Type = {
7173 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
7174 /*tp_name*/ "bpy_struct",
7175 /*tp_basicsize*/ sizeof(BPy_StructRNA),
7176 /*tp_itemsize*/ 0,
7177 /*tp_dealloc*/ pyrna_struct_dealloc,
7178 /*tp_vectorcall_offset*/ 0,
7179 /*tp_getattr*/ nullptr,
7180 /*tp_setattr*/ nullptr,
7181 /*tp_as_async*/ nullptr,
7182 /*tp_repr*/ (reprfunc)pyrna_struct_repr,
7183 /*tp_as_number*/ nullptr,
7184 /*tp_as_sequence*/ &pyrna_struct_as_sequence,
7185 /*tp_as_mapping*/ &pyrna_struct_as_mapping,
7186 /*tp_hash*/ (hashfunc)pyrna_struct_hash,
7187 /*tp_call*/ nullptr,
7188 /*tp_str*/ (reprfunc)pyrna_struct_str,
7189 /*tp_getattro*/ (getattrofunc)pyrna_struct_getattro,
7190 /*tp_setattro*/ (setattrofunc)pyrna_struct_setattro,
7191 /*tp_as_buffer*/ nullptr,
7192 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
7193#ifdef USE_PYRNA_STRUCT_REFERENCE
7194 | Py_TPFLAGS_HAVE_GC
7195#endif
7196 ,
7197 /*tp_doc*/ nullptr,
7198#ifdef USE_PYRNA_STRUCT_REFERENCE
7199 /*tp_traverse*/ (traverseproc)pyrna_struct_traverse,
7200 /*tp_clear*/ (inquiry)pyrna_struct_clear,
7201#else
7202 /*tp_traverse*/ nullptr,
7203 /*tp_clear*/ nullptr,
7204#endif /* !USE_PYRNA_STRUCT_REFERENCE */
7205 /*tp_richcompare*/ (richcmpfunc)pyrna_struct_richcmp,
7206#ifdef USE_WEAKREFS
7207 /*tp_weaklistoffset*/ offsetof(BPy_StructRNA, in_weakreflist),
7208#else
7209 0,
7210#endif
7211 /*tp_iter*/ nullptr,
7212 /*tp_iternext*/ nullptr,
7213 /*tp_methods*/ pyrna_struct_methods,
7214 /*tp_members*/ nullptr,
7215 /*tp_getset*/ pyrna_struct_getseters,
7216 /*tp_base*/ nullptr,
7217 /*tp_dict*/ nullptr,
7218 /*tp_descr_get*/ nullptr,
7219 /*tp_descr_set*/ nullptr,
7220 /*tp_dictoffset*/ 0,
7221 /*tp_init*/ pyrna_struct_init,
7222 /*tp_alloc*/ nullptr,
7223 /*tp_new*/ pyrna_struct_new,
7224 /*tp_free*/ nullptr,
7225 /*tp_is_gc*/ nullptr,
7226 /*tp_bases*/ nullptr,
7227 /*tp_mro*/ nullptr,
7228 /*tp_cache*/ nullptr,
7229 /*tp_subclasses*/ nullptr,
7230 /*tp_weaklist*/ nullptr,
7231 /*tp_del*/ nullptr,
7232 /*tp_version_tag*/ 0,
7233 /*tp_finalize*/ nullptr,
7234 /*tp_vectorcall*/ nullptr,
7235};
7236
7237static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject * /*kwds*/)
7238{
7239 if (PyTuple_GET_SIZE(args) != 1) {
7240 PyErr_Format(PyExc_TypeError, "bpy_struct.__new__(struct): expected a single argument");
7241 return nullptr;
7242 }
7243
7244 PyObject *arg_1 = PyTuple_GET_ITEM(args, 0);
7245
7246 /* Ignore the special 'PyCapsule' argument used only by internal bpy_rna code. */
7247 if (!PyCapsule_CheckExact(arg_1)) {
7248 BPy_StructRNA *base = reinterpret_cast<BPy_StructRNA *>(arg_1);
7249 /* Error, invalid type given. */
7250 if (!PyType_IsSubtype(Py_TYPE(base), &pyrna_struct_Type)) {
7251 PyErr_Format(
7252 PyExc_TypeError,
7253 "bpy_struct.__new__(struct): struct type '%.200s' is not a subtype of bpy_struct",
7254 Py_TYPE(base)->tp_name);
7255 return nullptr;
7256 }
7257 /* Same type, simply use the given data. */
7258 if (Py_TYPE(base) == type) {
7259 BLI_assert(base->ptr.has_value());
7260 Py_INCREF(base);
7261 return reinterpret_cast<PyObject *>(base);
7262 }
7263 /* NOTE: Further copy of the 'base' content into the new object will happen in
7264 * #pyrna_struct_init. */
7265 }
7266
7267 /* Only allocate the #PyObject data, do not construct/initialize anything else. */
7268 PyObject *self = type->tp_alloc(type, 0);
7269 BPy_StructRNA *self_struct = reinterpret_cast<BPy_StructRNA *>(self);
7270 if (self) {
7271#ifdef USE_PYRNA_STRUCT_REFERENCE
7272 /* #PyType_GenericAlloc will have set tracking.
7273 * We only want tracking when `StructRNA.reference` has been set. */
7274 PyObject_GC_UnTrack(self);
7275#endif
7276 self_struct->ptr = std::nullopt;
7277 }
7278 /* Pass on exception & nullptr if tp_alloc fails. */
7279 return self;
7280}
7281
7282static int pyrna_struct_init(PyObject *self, PyObject *args, PyObject * /*kwds*/)
7283{
7284 BPy_StructRNA *self_struct = reinterpret_cast<BPy_StructRNA *>(self);
7285
7286 size_t args_num = PyTuple_GET_SIZE(args);
7287 if (args_num != 1) {
7288 PyErr_Format(PyExc_TypeError, "bpy_struct.__init__(self, struct): expected a single argument");
7289 return -1;
7290 }
7291
7292 PyObject *arg_1 = PyTuple_GET_ITEM(args, 0);
7293 const PointerRNA *ptr = nullptr;
7294 if (PyCapsule_CheckExact(arg_1)) {
7295 /* `bpy_rna` internal code will call object creation with a PyCapsule argument wrapping up a
7296 * PointerRNA pointer. */
7297 ptr = static_cast<PointerRNA *>(
7298 PyCapsule_GetPointer(arg_1, BPy_capsule_PointerRNA_identifier));
7299 }
7300 else {
7301 BPy_StructRNA *base_struct = reinterpret_cast<BPy_StructRNA *>(arg_1);
7302
7303 /* Error, invalid type given. */
7304 if (!PyType_IsSubtype(Py_TYPE(base_struct), &pyrna_struct_Type)) {
7305 PyErr_Format(PyExc_TypeError,
7306 "bpy_struct.__init__(self, struct): struct type '%.200s' is not a subtype of "
7307 "bpy_struct",
7308 Py_TYPE(base_struct)->tp_name);
7309 return -1;
7310 }
7311 /* Same object as the 'base' argument (see #pyrna_struct_new), nothing to do . */
7312 if (base_struct == self_struct) {
7313 BLI_assert(self_struct->ptr.has_value());
7314 return 0;
7315 }
7316
7317 /* Else, use data from the base to initialize this object. */
7318 ptr = &base_struct->ptr.value();
7319 }
7320
7321 if (ptr == nullptr) {
7322 PyErr_Format(PyExc_TypeError,
7323 "bpy_struct.__init__(self, struct): failed to get a valid PointerRNA data "
7324 "from the given `struct` argument");
7325 return -1;
7326 }
7327
7328 self_struct->ptr.reset();
7329 self_struct->ptr = *ptr;
7330
7331 return 0;
7332}
7333
7334/* Own dealloc so that the PointerRNA can be destructed, and the IDProperty storage can be freed if
7335 * needed.
7336 *
7337 * Note: This should rather be in `tp_finalize` (aka `__del__`), but static types default dealloc
7338 * never calls this. */
7339static void pyrna_struct_dealloc(PyObject *self)
7340{
7341 /* Save the current exception, if any. */
7342 PyObject *error_type, *error_value, *error_traceback;
7343 PyErr_Fetch(&error_type, &error_value, &error_traceback);
7344
7345 BPy_StructRNA *self_struct = reinterpret_cast<BPy_StructRNA *>(self);
7346
7347#ifdef PYRNA_FREE_SUPPORT
7348 if (self_struct->freeptr && self_struct->ptr->data) {
7349 IDP_FreeProperty(self_struct->ptr->data);
7350 self_struct->ptr->data = nullptr;
7351 }
7352#endif /* PYRNA_FREE_SUPPORT */
7353
7354#ifdef USE_WEAKREFS
7355 if (self_struct->in_weakreflist != nullptr) {
7356 PyObject_ClearWeakRefs(self);
7357 }
7358#endif
7359
7360#ifdef USE_PYRNA_STRUCT_REFERENCE
7361 if (self_struct->reference) {
7362 PyObject_GC_UnTrack(self);
7363 pyrna_struct_clear(self_struct);
7364 }
7365 else {
7366 PyTypeObject *base = Py_TYPE(self)->tp_base;
7367 /* Python temporarily tracks these types when freeing, see Python bug 26617. */
7368 if (base && PyType_IS_GC(base)) {
7369 PyObject_GC_UnTrack(self);
7370 }
7371 BLI_assert(!PyObject_GC_IsTracked(self));
7372 }
7373#endif /* !USE_PYRNA_STRUCT_REFERENCE */
7374
7375 self_struct->ptr.~optional();
7376
7377 Py_TYPE(self)->tp_free(self);
7378
7379 /* Restore the saved exception. */
7380 PyErr_Restore(error_type, error_value, error_traceback);
7381}
7382
7384
7385/*-----------------------BPy_PropertyRNA method def------------------------------*/
7386
7387/* -------------------------------------------------------------------- */
7405
7406static PyObject *pyrna_property_new(PyTypeObject *type, PyObject *args, PyObject * /*kwds*/);
7407static int pyrna_property_init(PyObject *self, PyObject *args, PyObject * /*kwds*/);
7408static void pyrna_property_dealloc(PyObject *self);
7409static int pyrna_property_array_init(PyObject *self, PyObject *args, PyObject * /*kwds*/);
7410
7411PyTypeObject pyrna_prop_Type = {
7412 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
7413 /*tp_name*/ "bpy_prop",
7414 /*tp_basicsize*/ sizeof(BPy_PropertyRNA),
7415 /*tp_itemsize*/ 0,
7416 /*tp_dealloc*/ pyrna_property_dealloc,
7417 /*tp_vectorcall_offset*/ 0,
7418 /*tp_getattr*/ nullptr,
7419 /*tp_setattr*/ nullptr,
7420 /*tp_as_async*/ nullptr,
7421 /*tp_repr*/ (reprfunc)pyrna_prop_repr,
7422 /*tp_as_number*/ nullptr,
7423 /*tp_as_sequence*/ nullptr,
7424 /*tp_as_mapping*/ nullptr,
7425 /*tp_hash*/ (hashfunc)pyrna_prop_hash,
7426 /*tp_call*/ nullptr,
7427 /*tp_str*/ (reprfunc)pyrna_prop_str,
7428 /*tp_getattro*/ nullptr,
7429 /*tp_setattro*/ nullptr,
7430 /*tp_as_buffer*/ nullptr,
7431 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
7432 /*tp_doc*/ nullptr,
7433 /*tp_traverse*/ nullptr,
7434 /*tp_clear*/ nullptr,
7435 /*tp_richcompare*/ (richcmpfunc)pyrna_prop_richcmp,
7436#ifdef USE_WEAKREFS
7437 /*tp_weaklistoffset*/ offsetof(BPy_PropertyRNA, in_weakreflist),
7438#else
7439 /*tp_weaklistoffset*/ 0,
7440#endif
7441 /*tp_iter*/ nullptr,
7442 /*tp_iternext*/ nullptr,
7443 /*tp_methods*/ pyrna_prop_methods,
7444 /*tp_members*/ nullptr,
7445 /*tp_getset*/ pyrna_prop_getseters,
7446 /*tp_base*/ nullptr,
7447 /*tp_dict*/ nullptr,
7448 /*tp_descr_get*/ nullptr,
7449 /*tp_descr_set*/ nullptr,
7450 /*tp_dictoffset*/ 0,
7451 /*tp_init*/ pyrna_property_init,
7452 /*tp_alloc*/ nullptr,
7453 /*tp_new*/ pyrna_property_new,
7454 /*tp_free*/ nullptr,
7455 /*tp_is_gc*/ nullptr,
7456 /*tp_bases*/ nullptr,
7457 /*tp_mro*/ nullptr,
7458 /*tp_cache*/ nullptr,
7459 /*tp_subclasses*/ nullptr,
7460 /*tp_weaklist*/ nullptr,
7461 /*tp_del*/ nullptr,
7462 /*tp_version_tag*/ 0,
7463 /*tp_finalize*/ nullptr,
7464 /*tp_vectorcall*/ nullptr,
7465};
7466
7468 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
7469 /*tp_name*/ "bpy_prop_array",
7470 /*tp_basicsize*/ sizeof(BPy_PropertyArrayRNA),
7471 /*tp_itemsize*/ 0,
7472 /*tp_dealloc*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7473 /*tp_vectorcall_offset*/ 0,
7474 /*tp_getattr*/ nullptr,
7475 /*tp_setattr*/ nullptr,
7476 /*tp_as_async*/ nullptr,
7477 /*tp_repr*/ (reprfunc)pyrna_prop_array_repr,
7478 /*tp_as_number*/ &pyrna_prop_array_as_number,
7479 /*tp_as_sequence*/ &pyrna_prop_array_as_sequence,
7480 /*tp_as_mapping*/ &pyrna_prop_array_as_mapping,
7481 /*tp_hash*/ nullptr,
7482 /*tp_call*/ nullptr,
7483 /*tp_str*/ nullptr,
7484 /*tp_getattro*/ (getattrofunc)pyrna_prop_array_getattro,
7485 /*tp_setattro*/ nullptr,
7486 /*tp_as_buffer*/ nullptr,
7487 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
7488 /*tp_doc*/ nullptr,
7489 /*tp_traverse*/ nullptr,
7490 /*tp_clear*/ nullptr,
7491 /*tp_richcompare*/ nullptr,
7492#ifdef USE_WEAKREFS
7493 /*tp_weaklistoffset*/ offsetof(BPy_PropertyArrayRNA, in_weakreflist),
7494#else
7495 /*tp_weaklistoffset*/ 0,
7496#endif
7497 /*tp_iter*/ (getiterfunc)pyrna_prop_array_iter,
7498 /*tp_iternext*/ nullptr,
7499 /*tp_methods*/ pyrna_prop_array_methods,
7500 /*tp_members*/ nullptr,
7501 /*tp_getset*/ nullptr /* Sub-classed: #pyrna_prop_getseters. */,
7502 /*tp_base*/ &pyrna_prop_Type,
7503 /*tp_dict*/ nullptr,
7504 /*tp_descr_get*/ nullptr,
7505 /*tp_descr_set*/ nullptr,
7506 /*tp_dictoffset*/ 0,
7507 /*tp_init*/ pyrna_property_array_init,
7508 /*tp_alloc*/ nullptr,
7509 /*tp_new*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7510 /*tp_free*/ nullptr,
7511 /*tp_is_gc*/ nullptr,
7512 /*tp_bases*/ nullptr,
7513 /*tp_mro*/ nullptr,
7514 /*tp_cache*/ nullptr,
7515 /*tp_subclasses*/ nullptr,
7516 /*tp_weaklist*/ nullptr,
7517 /*tp_del*/ nullptr,
7518 /*tp_version_tag*/ 0,
7519 /*tp_finalize*/ nullptr,
7520 /*tp_vectorcall*/ nullptr,
7521};
7522
7524 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
7525 /*tp_name*/ "bpy_prop_collection",
7526 /*tp_basicsize*/ sizeof(BPy_PropertyRNA),
7527 /*tp_itemsize*/ 0,
7528 /*tp_dealloc*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7529 /*tp_vectorcall_offset*/ 0,
7530 /*tp_getattr*/ nullptr,
7531 /*tp_setattr*/ nullptr,
7532 /*tp_as_async*/ nullptr,
7533 /*tp_repr*/ nullptr, /* Sub-classed, no need to define. */
7534 /*tp_as_number*/ &pyrna_prop_collection_as_number,
7535 /*tp_as_sequence*/ &pyrna_prop_collection_as_sequence,
7536 /*tp_as_mapping*/ &pyrna_prop_collection_as_mapping,
7537 /*tp_hash*/ nullptr,
7538 /*tp_call*/ nullptr,
7539 /*tp_str*/ nullptr,
7540 /*tp_getattro*/ (getattrofunc)pyrna_prop_collection_getattro,
7541 /*tp_setattro*/ (setattrofunc)pyrna_prop_collection_setattro,
7542 /*tp_as_buffer*/ nullptr,
7543 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
7544 /*tp_doc*/ nullptr,
7545 /*tp_traverse*/ nullptr,
7546 /*tp_clear*/ nullptr,
7547 /*tp_richcompare*/ nullptr,
7548#ifdef USE_WEAKREFS
7549 /*tp_weaklistoffset*/ offsetof(BPy_PropertyRNA, in_weakreflist),
7550#else
7551 /*tp_weaklistoffset*/ 0,
7552#endif
7553 /*tp_iter*/ (getiterfunc)pyrna_prop_collection_iter,
7554 /*tp_iternext*/ nullptr,
7555 /*tp_methods*/ pyrna_prop_collection_methods,
7556 /*tp_members*/ nullptr,
7557 /*tp_getset*/ nullptr /*Sub-classed: see #pyrna_prop_getseters. */,
7558 /*tp_base*/ &pyrna_prop_Type,
7559 /*tp_dict*/ nullptr,
7560 /*tp_descr_get*/ nullptr,
7561 /*tp_descr_set*/ nullptr,
7562 /*tp_dictoffset*/ 0,
7563 /*tp_init*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7564 /*tp_alloc*/ nullptr,
7565 /*tp_new*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7566 /*tp_free*/ nullptr,
7567 /*tp_is_gc*/ nullptr,
7568 /*tp_bases*/ nullptr,
7569 /*tp_mro*/ nullptr,
7570 /*tp_cache*/ nullptr,
7571 /*tp_subclasses*/ nullptr,
7572 /*tp_weaklist*/ nullptr,
7573 /*tp_del*/ nullptr,
7574 /*tp_version_tag*/ 0,
7575 /*tp_finalize*/ nullptr,
7576 /*tp_vectorcall*/ nullptr,
7577};
7578
7579/* only for add/remove/move methods */
7581 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
7582 /*tp_name*/ "bpy_prop_collection_idprop",
7583 /*tp_basicsize*/ sizeof(BPy_PropertyRNA),
7584 /*tp_itemsize*/ 0,
7585 /*tp_dealloc*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7586 /*tp_vectorcall_offset*/ 0,
7587 /*tp_getattr*/ nullptr,
7588 /*tp_setattr*/ nullptr,
7589 /*tp_compare*/ nullptr, /* DEPRECATED. */
7590 /*tp_repr*/ nullptr, /* Sub-classed, no need to define. */
7591 /*tp_as_number*/ nullptr,
7592 /*tp_as_sequence*/ nullptr,
7593 /*tp_as_mapping*/ nullptr,
7594 /*tp_hash*/ nullptr,
7595 /*tp_call*/ nullptr,
7596 /*tp_str*/ nullptr,
7597 /*tp_getattro*/ nullptr,
7598 /*tp_setattro*/ nullptr,
7599 /*tp_as_buffer*/ nullptr,
7600 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
7601 /*tp_doc*/ nullptr,
7602 /*tp_traverse*/ nullptr,
7603 /*tp_clear*/ nullptr,
7604 /*tp_richcompare*/ nullptr,
7605#ifdef USE_WEAKREFS
7606 /*tp_weaklistoffset*/ offsetof(BPy_PropertyRNA, in_weakreflist),
7607#else
7608 /*tp_weaklistoffset*/ 0,
7609#endif
7610 /*tp_iter*/ nullptr,
7611 /*tp_iternext*/ nullptr,
7613 /*tp_members*/ nullptr,
7614 /*tp_getset*/ nullptr /* Sub-classed: #pyrna_prop_getseters. */,
7615 /*tp_base*/ &pyrna_prop_collection_Type,
7616 /*tp_dict*/ nullptr,
7617 /*tp_descr_get*/ nullptr,
7618 /*tp_descr_set*/ nullptr,
7619 /*tp_dictoffset*/ 0,
7620 /*tp_init*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7621 /*tp_alloc*/ nullptr,
7622 /*tp_new*/ nullptr, /* Inherited from #pyrna_prop_Type. */
7623 /*tp_free*/ nullptr,
7624 /*tp_is_gc*/ nullptr,
7625 /*tp_bases*/ nullptr,
7626 /*tp_mro*/ nullptr,
7627 /*tp_cache*/ nullptr,
7628 /*tp_subclasses*/ nullptr,
7629 /*tp_weaklist*/ nullptr,
7630 /*tp_del*/ nullptr,
7631 /*tp_version_tag*/ 0,
7632 /*tp_finalize*/ nullptr,
7633 /*tp_vectorcall*/ nullptr,
7634};
7635
7636static PyObject *pyrna_property_new(PyTypeObject *type, PyObject *args, PyObject * /*kwds*/)
7637{
7638 if (PyTuple_GET_SIZE(args) != 1) {
7639 PyErr_Format(PyExc_TypeError, "bpy_prop.__new__(property): expected a single argument");
7640 return nullptr;
7641 }
7642
7643 PyObject *arg_1 = PyTuple_GET_ITEM(args, 0);
7644
7645 /* Ignore the special 'PyCapsule' argument used only by internal bpy_rna code. */
7646 if (!PyCapsule_CheckExact(arg_1)) {
7647 BPy_PropertyRNA *base = reinterpret_cast<BPy_PropertyRNA *>(arg_1);
7648 /* Error, invalid type given. */
7649 if (!PyType_IsSubtype(Py_TYPE(base), &pyrna_prop_Type)) {
7650 PyErr_Format(
7651 PyExc_TypeError,
7652 "bpy_prop.__new__(property): property type '%.200s' is not a subtype of bpy_prop",
7653 Py_TYPE(base)->tp_name);
7654 return nullptr;
7655 }
7656 /* Same type, simply use the given data. */
7657 if (Py_TYPE(base) == type) {
7658 BLI_assert(base->ptr.has_value());
7659 Py_INCREF(base);
7660 return reinterpret_cast<PyObject *>(base);
7661 }
7662 /* NOTE: Further copy of the 'base' content into the new object will happen in
7663 * #pyrna_property_init. */
7664 }
7665
7666 /* Only allocate the #PyObject data, do not construct/initialize anything else. */
7667 PyObject *self = type->tp_alloc(type, 0);
7668 BPy_PropertyRNA *self_property = reinterpret_cast<BPy_PropertyRNA *>(self);
7669 if (self) {
7670 self_property->ptr = std::nullopt;
7671 }
7672 /* Pass on exception & nullptr if tp_alloc fails. */
7673 return self;
7674}
7675
7676static int pyrna_property_init(PyObject *self, PyObject *args, PyObject * /*kwds*/)
7677{
7678 BPy_PropertyRNA *self_property = reinterpret_cast<BPy_PropertyRNA *>(self);
7679
7680 size_t args_num = PyTuple_GET_SIZE(args);
7681 if (args_num != 1) {
7682 PyErr_Format(PyExc_TypeError, "bpy_prop.__init__(self, property): expected a single argument");
7683 return -1;
7684 }
7685
7686 PyObject *arg_1 = PyTuple_GET_ITEM(args, 0);
7687 const PointerRNA *ptr = nullptr;
7688 PropertyRNA *prop = nullptr;
7689 if (PyCapsule_CheckExact(arg_1)) {
7690 /* `bpy_rna` internal code will call object creation with a PyCapsule argument wrapping up a
7691 * PointerRNA and PropertyRNA pointers. */
7692 BPy_PropertyPointerRNA_Reference *pypropptr_rna =
7693 static_cast<BPy_PropertyPointerRNA_Reference *>(
7694 PyCapsule_GetPointer(arg_1, BPy_PropertyPointerRNA_capsule_identifier));
7695 if (pypropptr_rna) {
7696 ptr = pypropptr_rna->ptr;
7697 prop = pypropptr_rna->prop;
7698 }
7699 }
7700 else {
7701 BPy_PropertyRNA *base_property = reinterpret_cast<BPy_PropertyRNA *>(arg_1);
7702
7703 /* Error, invalid type given. */
7704 if (!PyType_IsSubtype(Py_TYPE(base_property), &pyrna_prop_Type)) {
7705 PyErr_Format(
7706 PyExc_TypeError,
7707 "bpy_prop.__init__(self, property): property type '%.200s' is not a subtype of bpy_prop",
7708 Py_TYPE(base_property)->tp_name);
7709 return -1;
7710 }
7711 /* Same object as the 'base' argument (see #pyrna_property_new), nothing to do . */
7712 if (base_property == self_property) {
7713 BLI_assert(self_property->ptr.has_value());
7714 return 0;
7715 }
7716 ptr = &base_property->ptr.value();
7717 prop = base_property->prop;
7718 }
7719
7720 self_property->ptr = *ptr;
7721 self_property->prop = prop;
7722
7723 return 0;
7724}
7725
7726static void pyrna_property_dealloc(PyObject *self)
7727{
7728 /* Save the current exception, if any. */
7729 PyObject *error_type, *error_value, *error_traceback;
7730 PyErr_Fetch(&error_type, &error_value, &error_traceback);
7731
7732 BPy_PropertyRNA *self_property = reinterpret_cast<BPy_PropertyRNA *>(self);
7733#ifdef USE_WEAKREFS
7734 if (self_property->in_weakreflist != nullptr) {
7735 PyObject_ClearWeakRefs(self);
7736 }
7737#endif
7738
7739 self_property->ptr.~optional();
7740
7741 Py_TYPE(self)->tp_free(self);
7742
7743 /* Restore the saved exception. */
7744 PyErr_Restore(error_type, error_value, error_traceback);
7745}
7746
7747static int pyrna_property_array_init(PyObject *self, PyObject *args, PyObject * /*kwds*/)
7748{
7749 BPy_PropertyArrayRNA *self_property = reinterpret_cast<BPy_PropertyArrayRNA *>(self);
7750
7751 size_t args_num = PyTuple_GET_SIZE(args);
7752 if (args_num != 1) {
7753 PyErr_Format(PyExc_TypeError,
7754 "bpy_prop_array.__init__(self, property): expected a single argument");
7755 return -1;
7756 }
7757
7758 PyObject *arg_1 = PyTuple_GET_ITEM(args, 0);
7759 const PointerRNA *ptr = nullptr;
7760 PropertyRNA *prop = nullptr;
7761 if (PyCapsule_CheckExact(arg_1)) {
7762 /* `bpy_rna` internal code will call object creation with a PyCapsule argument wrapping up a
7763 * PointerRNA and PropertyRNA pointers. */
7764 BPy_PropertyPointerRNA_Reference *pypropptr_rna =
7765 static_cast<BPy_PropertyPointerRNA_Reference *>(
7766 PyCapsule_GetPointer(arg_1, BPy_PropertyPointerRNA_capsule_identifier));
7767 if (pypropptr_rna) {
7768 ptr = pypropptr_rna->ptr;
7769 prop = pypropptr_rna->prop;
7770 }
7771 }
7772 else {
7773 BPy_PropertyArrayRNA *base_property = reinterpret_cast<BPy_PropertyArrayRNA *>(arg_1);
7774
7775 /* Error, invalid type given. */
7776 if (!PyType_IsSubtype(Py_TYPE(base_property), &pyrna_prop_array_Type)) {
7777 PyErr_Format(PyExc_TypeError,
7778 "bpy_prop_array.__init__(self, property): property type '%.200s' is not a "
7779 "subtype of bpy_prop_array",
7780 Py_TYPE(base_property)->tp_name);
7781 return -1;
7782 }
7783 /* Same object as the 'base' argument (see #pyrna_property_new), nothing to do . */
7784 if (base_property == self_property) {
7785 BLI_assert(self_property->ptr.has_value());
7786 return 0;
7787 }
7788 ptr = &base_property->ptr.value();
7789 prop = base_property->prop;
7790 }
7791
7792 self_property->prop = prop;
7793 self_property->arraydim = 0;
7794 self_property->arrayoffset = 0;
7795 self_property->ptr = *ptr;
7796
7797 return 0;
7798}
7799
7800#ifdef USE_PYRNA_ITER
7801/* --- collection iterator: start --- */
7802/* Wrap RNA collection iterator functions. */
7803/*
7804 * RNA_property_collection_begin(...)
7805 * RNA_property_collection_next(...)
7806 * RNA_property_collection_end(...)
7807 */
7808
7809static PyObject *pyrna_prop_collection_iter_new(PyTypeObject *type,
7810 PyObject * /*args*/,
7811 PyObject * /*kwds*/);
7812static int pyrna_prop_collection_iter_init(PyObject *self,
7813 PyObject * /*args*/,
7814 PyObject * /*kwds*/);
7815static void pyrna_prop_collection_iter_dealloc(PyObject *self);
7816static PyObject *pyrna_prop_collection_iter_next(PyObject *self);
7817
7818static PyTypeObject pyrna_prop_collection_iter_Type = {
7819 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
7820 /*tp_name*/ "bpy_prop_collection_iter",
7821 /*tp_basicsize*/ sizeof(BPy_PropertyCollectionIterRNA),
7822 /*tp_itemsize*/ 0,
7824 /*tp_vectorcall_offset*/ 0,
7825 /*tp_getattr*/ nullptr,
7826 /*tp_setattr*/ nullptr,
7827 /*tp_as_async*/ nullptr,
7828 /*tp_repr*/ nullptr, /* No need to define, sub-classed. */
7829 /*tp_as_number*/ nullptr,
7830 /*tp_as_sequence*/ nullptr,
7831 /*tp_as_mapping*/ nullptr,
7832 /*tp_hash*/ nullptr,
7833 /*tp_call*/ nullptr,
7834 /*tp_str*/ nullptr,
7835 /*tp_getattro*/ PyObject_GenericGetAttr,
7836 /*tp_setattro*/ nullptr,
7837 /*tp_as_buffer*/ nullptr,
7838 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
7839 /*tp_doc*/ nullptr,
7840 /*tp_traverse*/ nullptr,
7841 /*tp_clear*/ nullptr,
7842 /*tp_richcompare*/ nullptr,
7843# ifdef USE_WEAKREFS
7844 /*tp_weaklistoffset*/ offsetof(BPy_PropertyCollectionIterRNA, in_weakreflist),
7845# else
7846 /*tp_weaklistoffset*/ 0,
7847# endif
7848 /*tp_iter*/ PyObject_SelfIter,
7849 /*tp_iternext*/ pyrna_prop_collection_iter_next,
7850 /*tp_methods*/ nullptr,
7851 /*tp_members*/ nullptr,
7852 /*tp_getset*/ nullptr,
7853 /*tp_base*/ nullptr,
7854 /*tp_dict*/ nullptr,
7855 /*tp_descr_get*/ nullptr,
7856 /*tp_descr_set*/ nullptr,
7857 /*tp_dictoffset*/ 0,
7859 /*tp_alloc*/ nullptr,
7861 /*tp_free*/ nullptr,
7862 /*tp_is_gc*/ nullptr,
7863 /*tp_bases*/ nullptr,
7864 /*tp_mro*/ nullptr,
7865 /*tp_cache*/ nullptr,
7866 /*tp_subclasses*/ nullptr,
7867 /*tp_weaklist*/ nullptr,
7868 /*tp_del*/ nullptr,
7869 /*tp_version_tag*/ 0,
7870 /*tp_finalize*/ nullptr,
7871 /*tp_vectorcall*/ nullptr,
7872};
7873
7874static PyObject *pyrna_prop_collection_iter_new(PyTypeObject *type,
7875 PyObject *args,
7876 PyObject * /*kwds*/)
7877{
7878 if (PyTuple_GET_SIZE(args) != 1) {
7879 PyErr_Format(PyExc_TypeError,
7880 "bpy_prop_collection_iter.__new__(arg): expected a single argument");
7881 return nullptr;
7882 }
7883
7884 PyObject *arg_1 = PyTuple_GET_ITEM(args, 0);
7885 /* Only accept the special 'PyCapsule' argument used by internal bpy_rna code. */
7886 if (!PyCapsule_CheckExact(arg_1)) {
7887 PyErr_Format(PyExc_TypeError,
7888 "bpy_prop_collection_iter.__new__(arg): arg type '%.200s' is not a PyCapsule",
7889 Py_TYPE(arg_1)->tp_name);
7890 return nullptr;
7891 }
7892
7893 /* Only allocate the #PyObject data, do not construct/initialize anything else. */
7894 PyObject *self = type->tp_alloc(type, 0);
7895 BPy_PropertyCollectionIterRNA *self_prop_iter =
7896 reinterpret_cast<BPy_PropertyCollectionIterRNA *>(self);
7897 if (self_prop_iter) {
7898 self_prop_iter->iter = std::nullopt;
7899 }
7900
7901 return self;
7902}
7903
7904static int pyrna_prop_collection_iter_init(PyObject *self, PyObject *args, PyObject * /*kwds*/)
7905{
7906 BPy_PropertyCollectionIterRNA *self_prop_iter =
7907 reinterpret_cast<BPy_PropertyCollectionIterRNA *>(self);
7908
7909 size_t args_num = PyTuple_GET_SIZE(args);
7910 if (args_num != 1) {
7911 PyErr_Format(
7912 PyExc_TypeError,
7913 "bpy_prop_collection_iter.__init__(self, arg): expected at most a single argument");
7914 return -1;
7915 }
7916
7917 PyObject *arg_1 = PyTuple_GET_ITEM(args, 0);
7918 const PointerRNA *ptr = nullptr;
7919 PropertyRNA *prop = nullptr;
7920 if (PyCapsule_CheckExact(arg_1)) {
7921 /* `bpy_rna` internal code will call object creation with a PyCapsule argument wrapping up a
7922 * PointerRNA and PropertyRNA pointers. */
7923 BPy_PropertyPointerRNA_Reference *pypropptr_rna =
7924 static_cast<BPy_PropertyPointerRNA_Reference *>(
7925 PyCapsule_GetPointer(arg_1, BPy_PropertyPointerRNA_capsule_identifier));
7926 if (pypropptr_rna) {
7927 ptr = pypropptr_rna->ptr;
7928 prop = pypropptr_rna->prop;
7929 }
7930 }
7931 else {
7932 PyErr_Format(
7933 PyExc_TypeError,
7934 "bpy_prop_collection_iter.__init__(self, arg): arg type '%.200s' is not a PyCapsule",
7935 Py_TYPE(arg_1)->tp_name);
7936 }
7937
7938 if (self_prop_iter->iter.has_value()) {
7939 RNA_property_collection_end(&self_prop_iter->iter.value());
7940 self_prop_iter->iter.reset();
7941 }
7942 self_prop_iter->iter = CollectionPropertyIterator();
7944 const_cast<PointerRNA *>(ptr), prop, &self_prop_iter->iter.value());
7945
7946 return 0;
7947}
7948
7950{
7951 /* Save the current exception, if any. */
7952 PyObject *error_type, *error_value, *error_traceback;
7953 PyErr_Fetch(&error_type, &error_value, &error_traceback);
7954
7955 BPy_PropertyCollectionIterRNA *self_property = reinterpret_cast<BPy_PropertyCollectionIterRNA *>(
7956 self);
7957# ifdef USE_WEAKREFS
7958 if (self_property->in_weakreflist != nullptr) {
7959 PyObject_ClearWeakRefs(self);
7960 }
7961# endif
7962
7963 if (self_property->iter.has_value()) {
7964 RNA_property_collection_end(&self_property->iter.value());
7965 self_property->iter.reset();
7966 }
7967
7968 Py_TYPE(self)->tp_free(self);
7969
7970 /* Restore the saved exception. */
7971 PyErr_Restore(error_type, error_value, error_traceback);
7972}
7973
7975{
7976 /* Pass the PointerRNA and PropertyRNA to `__new__`/`__init__` functions as an opaque PyCapsule
7977 * object. */
7978 BPy_PropertyPointerRNA_Reference prop_ptr{ptr, prop};
7979 PyObject *pypropptr_rna = PyCapsule_New(
7980 &prop_ptr, BPy_PropertyPointerRNA_capsule_identifier, nullptr);
7981
7982 PyObject *self = PyObject_CallOneArg(
7983 reinterpret_cast<PyObject *>(&pyrna_prop_collection_iter_Type), pypropptr_rna);
7984 BPy_PropertyCollectionIterRNA *self_property = reinterpret_cast<BPy_PropertyCollectionIterRNA *>(
7985 self);
7986
7987 BLI_assert(self_property->iter.has_value());
7988 Py_DECREF(pypropptr_rna);
7989
7990# ifdef USE_WEAKREFS
7991 self_property->in_weakreflist = nullptr;
7992# else
7993 UNUSED_VARS_NDEBUG(self_property);
7994# endif
7995
7996 return self;
7997}
7998
7999static PyObject *pyrna_prop_collection_iter(PyObject *self)
8000{
8001 BPy_PropertyRNA *self_property = reinterpret_cast<BPy_PropertyRNA *>(self);
8002 return pyrna_prop_collection_iter_CreatePyObject(&self_property->ptr.value(),
8003 self_property->prop);
8004}
8005
8006static PyObject *pyrna_prop_collection_iter_next(PyObject *self)
8007{
8008 BPy_PropertyCollectionIterRNA *self_property = reinterpret_cast<BPy_PropertyCollectionIterRNA *>(
8009 self);
8010 if (self_property->iter->valid == false) {
8011 PyErr_SetNone(PyExc_StopIteration);
8012 return nullptr;
8013 }
8014
8015 PyObject *iter_data = pyrna_struct_CreatePyObject(&self_property->iter->ptr);
8016
8017# ifdef USE_PYRNA_STRUCT_REFERENCE
8018 if (iter_data) { /* Unlikely, but may fail. */
8019 BPy_StructRNA *iter_data_struct = reinterpret_cast<BPy_StructRNA *>(iter_data);
8020 if (iter_data != Py_None) {
8021 /* hold a reference to the iterator since it may have
8022 * allocated memory `pyrna` needs. eg: introspecting dynamic enum's. */
8023 /* TODO: we could have an API call to know if this is
8024 * needed since most collections don't */
8025 pyrna_struct_reference_set(iter_data_struct, self);
8026 }
8027 }
8028# endif /* !USE_PYRNA_STRUCT_REFERENCE */
8029
8030 RNA_property_collection_next(&self_property->iter.value());
8031
8032 return iter_data;
8033}
8034
8035/* --- collection iterator: end --- */
8036#endif /* !USE_PYRNA_ITER */
8037
8039
8040/*-----------------------BPy_PropertyRNA method def------------------------------*/
8041
8042/* -------------------------------------------------------------------- */
8045
8046static void pyrna_func_dealloc(PyObject *self);
8047
8048PyTypeObject pyrna_func_Type = {
8049 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
8050 /*tp_name*/ "bpy_func",
8051 /*tp_basicsize*/ sizeof(BPy_FunctionRNA),
8052 /*tp_itemsize*/ 0,
8053 /*tp_dealloc*/ pyrna_func_dealloc,
8054 /*tp_vectorcall_offset*/ offsetof(BPy_FunctionRNA, vectorcall),
8055 /*tp_getattr*/ nullptr,
8056 /*tp_setattr*/ nullptr,
8057 /*tp_as_async*/ nullptr,
8058 /*tp_repr*/ (reprfunc)pyrna_func_repr,
8059 /*tp_as_number*/ nullptr,
8060 /*tp_as_sequence*/ nullptr,
8061 /*tp_as_mapping*/ nullptr,
8062 /*tp_hash*/ nullptr,
8063 /*tp_call*/ PyVectorcall_Call,
8064 /*tp_str*/ nullptr,
8065 /*tp_getattro*/ nullptr,
8066 /*tp_setattro*/ nullptr,
8067 /*tp_as_buffer*/ nullptr,
8068 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_VECTORCALL,
8069 /*tp_doc*/ nullptr,
8070 /*tp_traverse*/ nullptr,
8071 /*tp_clear*/ nullptr,
8072 /*tp_richcompare*/ nullptr,
8073#ifdef USE_WEAKREFS
8074 /*tp_weaklistoffset*/ offsetof(BPy_PropertyRNA, in_weakreflist),
8075#else
8076 /*tp_weaklistoffset*/ 0,
8077#endif
8078 /*tp_iter*/ nullptr,
8079 /*tp_iternext*/ nullptr,
8080 /*tp_methods*/ nullptr,
8081 /*tp_members*/ nullptr,
8082 /*tp_getset*/ pyrna_func_getseters,
8083 /*tp_base*/ nullptr,
8084 /*tp_dict*/ nullptr,
8085 /*tp_descr_get*/ nullptr,
8086 /*tp_descr_set*/ nullptr,
8087 /*tp_dictoffset*/ 0,
8088 /*tp_init*/ nullptr,
8089 /*tp_alloc*/ nullptr,
8090 /*tp_new*/ nullptr,
8091 /*tp_free*/ nullptr,
8092 /*tp_is_gc*/ nullptr,
8093 /*tp_bases*/ nullptr,
8094 /*tp_mro*/ nullptr,
8095 /*tp_cache*/ nullptr,
8096 /*tp_subclasses*/ nullptr,
8097 /*tp_weaklist*/ nullptr,
8098 /*tp_del*/ nullptr,
8099 /*tp_version_tag*/ 0,
8100 /*tp_finalize*/ nullptr,
8101 /*tp_vectorcall*/ nullptr,
8102};
8103
8105{
8106 PyObject *self = pyrna_func_Type.tp_alloc(&pyrna_func_Type, 0);
8107 BPy_FunctionRNA *pyfunc = reinterpret_cast<BPy_FunctionRNA *>(self);
8108 if (pyfunc) {
8109 pyfunc->func = func;
8110 pyfunc->ptr = *ptr;
8112 }
8113
8114 if (!pyfunc) {
8115 PyErr_SetString(PyExc_MemoryError, "couldn't create bpy_func object");
8116 return nullptr;
8117 }
8118
8119 BLI_assert(pyfunc->ptr.has_value());
8120
8121 return reinterpret_cast<PyObject *>(pyfunc);
8122}
8123
8124static void pyrna_func_dealloc(PyObject *self)
8125{
8126 /* Save the current exception, if any. */
8127 PyObject *error_type, *error_value, *error_traceback;
8128 PyErr_Fetch(&error_type, &error_value, &error_traceback);
8129
8130 BPy_FunctionRNA *self_func = reinterpret_cast<BPy_FunctionRNA *>(self);
8131
8132#ifdef USE_WEAKREFS
8133 if (self_func->in_weakreflist != nullptr) {
8134 PyObject_ClearWeakRefs(self);
8135 }
8136#endif
8137
8138 self_func->ptr.~optional();
8139
8140 Py_TYPE(self)->tp_free(self);
8141
8142 /* Restore the saved exception. */
8143 PyErr_Restore(error_type, error_value, error_traceback);
8144}
8145
8147
8148static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
8149{
8150 Py_INCREF(newclass);
8151
8152 if (PyObject *oldclass = static_cast<PyObject *>(RNA_struct_py_type_get(srna))) {
8153 PyC_ObSpit("RNA WAS SET - ", oldclass);
8154 Py_DECREF(oldclass);
8155 }
8156 RNA_struct_py_type_set(srna, (void *)newclass); /* Store for later use */
8157
8158 /* Not 100% needed, but useful,
8159 * having an instance within a type looks wrong, but this instance _is_ an RNA type. */
8160
8161 /* Python deals with the circular reference. */
8162 PointerRNA ptr = RNA_pointer_create_discrete(nullptr, &RNA_Struct, srna);
8163
8164 /* NOTE: using `pyrna_struct_CreatePyObject(&ptr)` is close to what is needed,
8165 * however the it isn't correct because the result of:
8166 * `type(bpy.types.Object.bl_rna) == bpy.types.Object`.
8167 * In this case the type of `bl_rna` should be `bpy.types.Struct`.
8168 * This is passed in explicitly, while #pyrna_struct_CreatePyObject could
8169 * take this as an argument it's such a corner case that using a lower level
8170 * function that takes the type is preferable. */
8171 {
8172 BLI_assert(RNA_struct_instance(&ptr) == nullptr);
8173 PyTypeObject *tp = (PyTypeObject *)pyrna_srna_Subtype(&RNA_Struct);
8174 PyObject *item = pyrna_struct_CreatePyObject_from_type(&ptr, tp, nullptr);
8175 Py_DECREF(tp); /* `srna` owns, can't hold a reference. */
8176
8177 /* NOTE: must set the class not the `__dict__`
8178 * else the internal slots are not updated correctly. */
8179 PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item);
8180 Py_DECREF(item);
8181 }
8182
8183 /* Add `staticmethod` and `classmethod` functions. */
8184 {
8185 const PointerRNA func_ptr = {nullptr, srna, nullptr};
8186 const ListBase *lb;
8187
8188 lb = RNA_struct_type_functions(srna);
8189 LISTBASE_FOREACH (Link *, link, lb) {
8190 FunctionRNA *func = (FunctionRNA *)link;
8191 const int flag = RNA_function_flag(func);
8192 if ((flag & FUNC_NO_SELF) && /* Is `staticmethod` or `classmethod`. */
8193 (flag & FUNC_REGISTER) == false) /* Is not for registration. */
8194 {
8195 /* We may want to set the type of this later. */
8196 PyObject *func_py = pyrna_func_CreatePyObject(&func_ptr, func);
8197 PyObject_SetAttrString(newclass, RNA_function_identifier(func), func_py);
8198 Py_DECREF(func_py);
8199 }
8200 }
8201 }
8202
8203 /* Done with RNA instance. */
8204}
8205
8209static PyObject *pyrna_srna_PyBase(StructRNA *srna)
8210{
8211 /* Assume RNA_struct_py_type_get(srna) was already checked. */
8212 StructRNA *base;
8213
8214 PyObject *py_base = nullptr;
8215
8216 /* Get the base type. */
8217 base = RNA_struct_base(srna);
8218
8219 if (base && base != srna) {
8220 // printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna);
8221 py_base = pyrna_srna_Subtype(base); //, bpy_types_dict);
8222 Py_DECREF(py_base); /* `srna` owns, this is only to pass as an argument. */
8223 }
8224
8225 if (py_base == nullptr) {
8226 py_base = (PyObject *)&pyrna_struct_Type;
8227 }
8228
8229 return py_base;
8230}
8231
8236static PyObject *bpy_types_dict = nullptr;
8237void BPY_rna_types_dict_set(PyObject *dict)
8238{
8239 bpy_types_dict = dict; /* Borrow. */
8240}
8241
8247static PyObject *pyrna_srna_ExternalType(StructRNA *srna)
8248{
8250
8251 const char *idname = RNA_struct_identifier(srna);
8252 PyObject *newclass = PyDict_GetItemString(bpy_types_dict, idname);
8253
8254 /* Sanity check, could skip this unless in debug mode. */
8255 if (newclass) {
8256 PyObject *base_compare = pyrna_srna_PyBase(srna);
8257 /* Can't do this because it gets super-classes values! */
8258 // PyObject *slots = PyObject_GetAttrString(newclass, "__slots__");
8259 /* Can do this, but faster not to. */
8260 // PyObject *bases = PyObject_GetAttrString(newclass, "__bases__");
8261 PyObject *tp_bases = ((PyTypeObject *)newclass)->tp_bases;
8262 PyObject *tp_slots = PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict,
8264
8265 if (tp_slots == nullptr) {
8266 CLOG_ERROR(
8267 BPY_LOG_RNA, "expected class '%s' to have __slots__ defined, see _bpy_types.py", idname);
8268 newclass = nullptr;
8269 }
8270 else if (PyTuple_GET_SIZE(tp_bases)) {
8271 PyObject *base = PyTuple_GET_ITEM(tp_bases, 0);
8272
8273 if (base_compare != base) {
8274 char pyob_info[256];
8275 PyC_ObSpitStr(pyob_info, sizeof(pyob_info), base_compare);
8277 "incorrect subclassing of SRNA '%s', expected '%s', see _bpy_types.py",
8278 idname,
8279 pyob_info);
8280 newclass = nullptr;
8281 }
8282 else {
8283 CLOG_TRACE(BPY_LOG_RNA, "SRNA sub-classed: '%s'", idname);
8284 }
8285 }
8286 }
8287
8288 return newclass;
8289}
8290
8296static PyObject *pyrna_srna_Subtype(StructRNA *srna)
8297{
8298 PyObject *newclass = nullptr;
8299
8300 /* Stupid/simple case. */
8301 if (srna == nullptr) {
8302 newclass = nullptr; /* Nothing to do. */
8303 } /* The class may have already been declared & allocated. */
8304 else if ((newclass = static_cast<PyObject *>(RNA_struct_py_type_get(srna)))) {
8305 /* Add a reference for the return value. */
8306 Py_INCREF(newclass);
8307 } /* Check if `_bpy_types.py` module has the class defined in it. */
8308 else if ((newclass = pyrna_srna_ExternalType(srna))) {
8309 pyrna_subtype_set_rna(newclass, srna);
8310 /* Add a reference for the return value. */
8311 Py_INCREF(newclass);
8312 } /* Create a new class instance with the C API
8313 * mainly for the purposing of matching the C/RNA type hierarchy. */
8314 else {
8315 /* subclass equivalents
8316 * - class myClass(myBase):
8317 * some = 'value' # or ...
8318 * - myClass = type(
8319 * name='myClass',
8320 * bases=(myBase,), dict={'__module__': 'bpy.types', '__slots__': ()}
8321 * )
8322 */
8323
8324 /* Assume `RNA_struct_py_type_get(srna)` was already checked. */
8325 PyObject *py_base = pyrna_srna_PyBase(srna);
8326 PyObject *metaclass;
8327 const char *idname = RNA_struct_identifier(srna);
8328
8329/* Remove `__doc__` for now because we don't need it to generate docs. */
8330#if 0
8331 const char *descr = RNA_struct_ui_description(srna);
8332 if (!descr) {
8333 descr = "(no docs)";
8334 }
8335#endif
8336
8338 !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type))
8339 {
8340 metaclass = (PyObject *)&pyrna_struct_meta_idprop_Type;
8341 }
8342 else {
8343 metaclass = (PyObject *)&PyType_Type;
8344 }
8345
8346/* Always use O not N when calling, N causes refcount errors. */
8347#if 0
8348 newclass = PyObject_CallFunction(
8349 metaclass, "s(O) {sss()}", idname, py_base, "__module__", "bpy.types", "__slots__");
8350#else
8351 {
8352 /* Longhand of the call above. */
8353 PyObject *args, *item, *value;
8354 int ok;
8355
8356 args = PyTuple_New(3);
8357
8358 /* arg[0] (name=...) */
8359 PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(idname));
8360
8361 /* arg[1] (bases=...) */
8362 PyTuple_SET_ITEM(args, 1, item = PyTuple_New(1));
8363 PyTuple_SET_ITEM(item, 0, Py_NewRef(py_base));
8364
8365 /* arg[2] (dict=...) */
8366 PyTuple_SET_ITEM(args, 2, item = PyDict_New());
8367 ok = PyDict_SetItem(item, bpy_intern_str___module__, bpy_intern_str_bpy_types);
8368 BLI_assert(ok != -1);
8369 ok = PyDict_SetItem(item, bpy_intern_str___slots__, value = PyTuple_New(0));
8370 Py_DECREF(value);
8371 BLI_assert(ok != -1);
8372
8373 newclass = PyObject_CallObject(metaclass, args);
8374 Py_DECREF(args);
8375
8376 (void)ok;
8377 }
8378#endif
8379
8380 /* Newclass will now have 2 ref's, ???,
8381 * probably 1 is internal since #Py_DECREF here segfaults. */
8382
8383 // PyC_ObSpit("new class ref", newclass);
8384
8385 if (newclass) {
8386 /* srna owns one, and the other is owned by the caller. */
8387 pyrna_subtype_set_rna(newclass, srna);
8388 }
8389 else {
8390 /* This should not happen. */
8391 CLOG_ERROR(BPY_LOG_RNA, "failed to register '%s'", idname);
8392 PyErr_Print();
8393 }
8394 }
8395
8396 return newclass;
8397}
8398
8403{
8404 if (ptr->type == &RNA_Struct) {
8405 return static_cast<StructRNA *>(ptr->data);
8406 }
8407
8408 return ptr->type;
8409}
8410
8415{
8417}
8418
8419/*-----------------------CreatePyObject---------------------------------*/
8420
8428 PyTypeObject *tp,
8429 void **instance)
8430{
8431 /* Pass the PointerRNA to `__new__`/`__init__` functions as an opaque PyCapsule object. */
8432 PyObject *pyptr_rna = PyCapsule_New(
8433 const_cast<PointerRNA *>(ptr), BPy_capsule_PointerRNA_identifier, nullptr);
8434
8435 BPy_StructRNA *pyrna = nullptr;
8436 if (tp) {
8437 pyrna = reinterpret_cast<BPy_StructRNA *>(
8438 PyObject_CallOneArg(reinterpret_cast<PyObject *>(tp), pyptr_rna));
8439 }
8440 else {
8441 CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type));
8442
8443 pyrna = reinterpret_cast<BPy_StructRNA *>(
8444 PyObject_CallOneArg(reinterpret_cast<PyObject *>(&pyrna_struct_Type), pyptr_rna));
8445 }
8446
8447#ifdef USE_PYRNA_STRUCT_REFERENCE
8448 /* #PyType_GenericAlloc will have set tracking.
8449 * We only want tracking when `StructRNA.reference` has been set. */
8450 if (pyrna != nullptr) {
8451 PyObject_GC_UnTrack(pyrna);
8452 }
8453#endif
8454
8455#ifdef USE_WEAKREFS
8456 if (pyrna != nullptr) {
8457 pyrna->in_weakreflist = nullptr;
8458 }
8459#endif
8460
8461 if (pyrna == nullptr) {
8462 if (!PyErr_Occurred()) {
8463 PyErr_SetString(PyExc_MemoryError, "couldn't create bpy_struct object");
8464 }
8465 return nullptr;
8466 }
8467
8468 BLI_assert(pyrna->ptr.has_value());
8469 Py_DECREF(pyptr_rna);
8470
8471 /* Blender's instance owns a reference (to avoid Python freeing it). */
8472 if (instance) {
8473 *instance = pyrna;
8474 Py_INCREF(pyrna);
8475 }
8476
8477#ifdef PYRNA_FREE_SUPPORT
8478 pyrna->freeptr = false;
8479#endif
8480
8481#ifdef USE_PYRNA_STRUCT_REFERENCE
8482 pyrna->reference = nullptr;
8483#endif
8484
8485 // PyC_ObSpit("NewStructRNA: ", (PyObject *)pyrna);
8486
8487#ifdef USE_PYRNA_INVALIDATE_WEAKREF
8488 if (ptr->owner_id) {
8489 id_weakref_pool_add(ptr->owner_id, (BPy_DummyPointerRNA *)pyrna);
8490 }
8491#endif
8492
8493 return reinterpret_cast<PyObject *>(pyrna);
8494}
8495
8497{
8498 /* NOTE: don't rely on this to return None since nullptr data with a valid type can often crash.
8499 */
8500 if (ptr->data == nullptr && ptr->type == nullptr) { /* Operator RNA has nullptr data. */
8501 Py_RETURN_NONE;
8502 }
8503
8504 BPy_StructRNA *pyrna = nullptr;
8505
8506 /* NOTE(@ideasman42): New in 2.8x, since not many types support instancing
8507 * we may want to use a flag to avoid looping over all classes. */
8508 void **instance = ptr->data ? RNA_struct_instance(ptr) : nullptr;
8509 if (instance && *instance) {
8510 pyrna = static_cast<BPy_StructRNA *>(*instance);
8511
8512 /* Refine may have changed types after the first instance was created. */
8513 if (ptr->type == pyrna->ptr->type) {
8514 Py_INCREF(pyrna);
8515 return reinterpret_cast<PyObject *>(pyrna);
8516 }
8517
8518 /* Existing users will need to use 'type_recast' method. */
8519 Py_DECREF(pyrna);
8520 *instance = nullptr;
8521 /* Continue as if no instance was available. */
8522 }
8523
8524 PyTypeObject *tp = reinterpret_cast<PyTypeObject *>(pyrna_struct_Subtype(ptr));
8525 pyrna = reinterpret_cast<BPy_StructRNA *>(
8527 Py_XDECREF(tp); /* `srna` owns, can't hold a reference. */
8528
8529 return reinterpret_cast<PyObject *>(pyrna);
8530}
8531
8533{
8534 if (ptr->type == &RNA_PrimitiveString) {
8535 const PrimitiveStringRNA *data = static_cast<const PrimitiveStringRNA *>(ptr->data);
8536 return PyC_UnicodeFromBytes(data->value);
8537 }
8538 if (ptr->type == &RNA_PrimitiveInt) {
8539 const PrimitiveIntRNA *data = static_cast<const PrimitiveIntRNA *>(ptr->data);
8540 return PyLong_FromLong(data->value);
8541 }
8542 if (ptr->type == &RNA_PrimitiveFloat) {
8543 const PrimitiveFloatRNA *data = static_cast<const PrimitiveFloatRNA *>(ptr->data);
8544 return PyFloat_FromDouble(data->value);
8545 }
8546 if (ptr->type == &RNA_PrimitiveBoolean) {
8547 const PrimitiveBooleanRNA *data = static_cast<const PrimitiveBooleanRNA *>(ptr->data);
8548 return PyBool_FromLong(data->value);
8549 }
8551}
8552
8554{
8555 PyTypeObject *type;
8556 if (RNA_property_array_check(prop)) {
8557 type = &pyrna_prop_array_Type;
8558 }
8559 else if (RNA_property_type(prop) == PROP_COLLECTION) {
8560 if (RNA_property_flag(prop) & PROP_IDPROPERTY) {
8562 }
8563 else {
8565 }
8566 }
8567 else {
8568 type = &pyrna_prop_Type;
8569 }
8570
8571 /* Pass the PointerRNA and PropertyRNA to `__new__`/`__init__` functions as an opaque PyCapsule
8572 * object. */
8573 BPy_PropertyPointerRNA_Reference prop_ptr{ptr, prop};
8574 PyObject *pypropptr_rna = PyCapsule_New(
8575 &prop_ptr, BPy_PropertyPointerRNA_capsule_identifier, nullptr);
8576
8577 BPy_PropertyRNA *pyrna = reinterpret_cast<BPy_PropertyRNA *>(
8578 PyObject_CallOneArg(reinterpret_cast<PyObject *>(type), pypropptr_rna));
8579
8580 if (pyrna == nullptr) {
8581 PyErr_SetString(PyExc_MemoryError, "couldn't create BPy_rna object");
8582 return nullptr;
8583 }
8584
8585 BLI_assert(pyrna->ptr.has_value());
8586 Py_DECREF(pypropptr_rna);
8587
8588#ifdef USE_WEAKREFS
8589 pyrna->in_weakreflist = nullptr;
8590#endif
8591
8592#ifdef USE_PYRNA_INVALIDATE_WEAKREF
8593 if (ptr->owner_id) {
8594 id_weakref_pool_add(ptr->owner_id, (BPy_DummyPointerRNA *)pyrna);
8595 }
8596#endif
8597
8598 return (PyObject *)pyrna;
8599}
8600
8602{
8603 if (id) {
8606 }
8607
8608 Py_RETURN_NONE;
8609}
8610
8611bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
8612{
8613 if (pyrna_id_CheckPyObject(obj)) {
8614 *id = ((BPy_StructRNA *)obj)->ptr->owner_id;
8615 return true;
8616 }
8617
8618 *id = nullptr;
8619 return false;
8620}
8621
8622bool pyrna_id_CheckPyObject(PyObject *obj)
8623{
8624 return BPy_StructRNA_Check(obj) && RNA_struct_is_ID(((BPy_StructRNA *)obj)->ptr->type);
8625}
8626
8628{
8629#ifdef USE_MATHUTILS /* Register mathutils callbacks, ok to run more than once. */
8632#endif
8633
8634/* For some reason MSVC complains of these. */
8635#if defined(_MSC_VER)
8636 pyrna_struct_meta_idprop_Type.tp_base = &PyType_Type;
8637#endif
8638
8639 /* metaclass */
8640 if (PyType_Ready(&pyrna_struct_meta_idprop_Type) < 0) {
8641 return;
8642 }
8643
8644 if (PyType_Ready(&pyrna_struct_Type) < 0) {
8645 return;
8646 }
8647
8648 if (PyType_Ready(&pyrna_prop_Type) < 0) {
8649 return;
8650 }
8651
8652 if (PyType_Ready(&pyrna_prop_array_Type) < 0) {
8653 return;
8654 }
8655
8656 if (PyType_Ready(&pyrna_prop_collection_Type) < 0) {
8657 return;
8658 }
8659
8660 if (PyType_Ready(&pyrna_prop_collection_idprop_Type) < 0) {
8661 return;
8662 }
8663
8664 if (PyType_Ready(&pyrna_func_Type) < 0) {
8665 return;
8666 }
8667
8668#ifdef USE_PYRNA_ITER
8669 if (PyType_Ready(&pyrna_prop_collection_iter_Type) < 0) {
8670 return;
8671 }
8672#endif
8673
8674#ifdef USE_PYRNA_INVALIDATE_WEAKREF
8675 BLI_assert(id_weakref_pool == nullptr);
8676 id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool");
8677#endif
8678}
8679
8681{
8682#ifdef USE_PYRNA_INVALIDATE_WEAKREF
8683 /* This can help track down which kinds of data were not released.
8684 * If they were in fact freed by Blender, printing their names
8685 * will crash giving a useful error with address sanitizer. The likely cause
8686 * for this list not being empty is a missing call to: #BKE_libblock_free_data_py. */
8687 const int id_weakref_pool_len = BLI_ghash_len(id_weakref_pool);
8688 if (id_weakref_pool_len != 0) {
8689 printf("Found %d unreleased ID's\n", id_weakref_pool_len);
8690 GHashIterator gh_iter;
8691 GHASH_ITER (gh_iter, id_weakref_pool) {
8692 ID *id = static_cast<ID *>(BLI_ghashIterator_getKey(&gh_iter));
8693 printf("ID: %s\n", id->name);
8694 }
8695 }
8696 BLI_ghash_free(id_weakref_pool, nullptr, id_weakref_pool_free_value_fn);
8697 id_weakref_pool = nullptr;
8698#endif
8699}
8700
8701/* 'bpy.data' from Python. */
8702static PointerRNA *rna_module_ptr = nullptr;
8704{
8705 BPy_StructRNA *pyrna;
8706
8707 /* For now, return the base RNA type rather than a real module. */
8710
8711 rna_module_ptr = &pyrna->ptr.value();
8712 return (PyObject *)pyrna;
8713}
8714
8716{
8717 if (rna_module_ptr) {
8718#if 0
8720#else
8721 rna_module_ptr->data = G_MAIN; /* Just set data is enough. */
8722#endif
8723 }
8724}
8725
8726#if 0
8727/* This is a way we can access doc-strings for RNA types
8728 * without having the data-types in Blender. */
8729PyObject *BPY_rna_doc()
8730{
8731
8732 /* For now, return the base RNA type rather than a real module. */
8734
8736}
8737#endif
8738
8739/* -------------------------------------------------------------------- */
8742
8751 std::optional<PointerRNA> ptr;
8754};
8755
8756static PyObject *bpy_types_module_getattro(PyObject *self, PyObject *pyname)
8757{
8758 BPy_TypesModule_State *state = static_cast<BPy_TypesModule_State *>(PyModule_GetState(self));
8759 BLI_assert(state->ptr.has_value());
8760
8761 PointerRNA newptr;
8762 PyObject *ret;
8763 const char *name = PyUnicode_AsUTF8(pyname);
8764
8765 if (name == nullptr) {
8766 PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string");
8767 ret = nullptr;
8768 }
8769 else if (RNA_property_collection_lookup_string(&state->ptr.value(), state->prop, name, &newptr))
8770 {
8771 ret = pyrna_struct_Subtype(&newptr);
8772 if (ret == nullptr) {
8773 PyErr_Format(PyExc_RuntimeError,
8774 "bpy.types.%.200s subtype could not be generated, this is a bug!",
8775 PyUnicode_AsUTF8(pyname));
8776 }
8777 }
8778 else {
8779#if 0
8780 PyErr_Format(PyExc_AttributeError,
8781 "bpy.types.%.200s RNA_Struct does not exist",
8782 PyUnicode_AsUTF8(pyname));
8783 return nullptr;
8784#endif
8785 /* The error raised here will be displayed. */
8786 ret = PyObject_GenericGetAttr(self, pyname);
8787 }
8788
8789 return ret;
8790}
8791
8792static PyObject *bpy_types_module_dir(PyObject *self)
8793{
8794 BPy_TypesModule_State *state = static_cast<BPy_TypesModule_State *>(PyModule_GetState(self));
8795 BLI_assert(state->ptr.has_value());
8796
8797 PyObject *ret = PyList_New(0);
8798
8799 RNA_PROP_BEGIN (&state->ptr.value(), itemptr, state->prop) {
8800 StructRNA *srna = static_cast<StructRNA *>(itemptr.data);
8801 PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna)));
8802 }
8804
8805 /* Include the modules `__dict__` for Python only types. */
8806 PyObject *submodule_dict = PyModule_GetDict(self);
8807 PyObject *key, *value;
8808 Py_ssize_t pos = 0;
8809 while (PyDict_Next(submodule_dict, &pos, &key, &value)) {
8810 PyList_Append(ret, key);
8811 }
8812 return ret;
8813}
8814
8815#ifdef __GNUC__
8816# ifdef __clang__
8817# pragma clang diagnostic push
8818# pragma clang diagnostic ignored "-Wcast-function-type"
8819# else
8820# pragma GCC diagnostic push
8821# pragma GCC diagnostic ignored "-Wcast-function-type"
8822# endif
8823#endif
8824
8825static PyMethodDef bpy_types_module_methods[] = {
8826 {"__getattr__", (PyCFunction)bpy_types_module_getattro, METH_O, nullptr},
8827 {"__dir__", (PyCFunction)bpy_types_module_dir, METH_NOARGS, nullptr},
8828 {nullptr, nullptr, 0, nullptr},
8829};
8830
8831#ifdef __GNUC__
8832# ifdef __clang__
8833# pragma clang diagnostic pop
8834# else
8835# pragma GCC diagnostic pop
8836# endif
8837#endif
8838
8839static void bpy_types_module_free(void *self)
8840{
8841 /* Module's `m_free` is quite different from `PyTypeObject` `tp_free`. It does not have to free
8842 * python-allocated memory (like the module state itself), but only memory managed outside of
8843 * Python. In that sense, it is way closer to `tp_finalize`. */
8844
8845 PyObject *submodule = static_cast<PyObject *>(self);
8847 PyModule_GetState(submodule));
8848
8849 state->ptr.~optional();
8850}
8851
8853 /* Wrap. */
8854 bpy_types_module_doc,
8855 "Access to internal Blender types.");
8856static PyModuleDef bpy_types_module_def = {
8857 /*m_base*/ PyModuleDef_HEAD_INIT,
8858 /*m_name*/ "bpy.types",
8859 /*m_doc*/ bpy_types_module_doc,
8860 /*m_size*/ sizeof(BPy_TypesModule_State),
8861 /*m_methods*/ bpy_types_module_methods,
8862 /*m_slots*/ nullptr,
8863 /*m_traverse*/ nullptr,
8864 /*m_clear*/ nullptr,
8865 /*m_free*/ bpy_types_module_free,
8866};
8867
8868PyObject *BPY_rna_types()
8869{
8870 PyObject *submodule = PyModule_Create(&bpy_types_module_def);
8872 PyModule_GetState(submodule));
8873
8875 state->prop = RNA_struct_find_property(&state->ptr.value(), "structs");
8876
8877 /* Internal base types we have no other accessors for. */
8878 {
8879 static PyTypeObject *pyrna_types[] = {
8887 };
8888
8889 PyObject *submodule_dict = PyModule_GetDict(submodule);
8890 for (int i = 0; i < ARRAY_SIZE(pyrna_types); i += 1) {
8891 PyDict_SetItemString(submodule_dict, pyrna_types[i]->tp_name, (PyObject *)pyrna_types[i]);
8892 }
8893 }
8894
8895 return submodule;
8896}
8897
8899{
8900 /* NOTE: Blender is generally functional without running this logic
8901 * however failure set the classes `bl_rna` (via `pyrna_subtype_set_rna`)
8902 * means *partially* initialized classes exist.
8903 * It's simpler to avoid this altogether as it's a corner case Python developers should
8904 * not have to concern themselves with as it could cause errors with RNA introspection.
8905 *
8906 * If the classes are accessed via `bpy.types` they will be initialized correctly
8907 * however classes can also be accessed via `bpy.types.ID.__subclasses__()`
8908 * which doesn't ensure the `bl_rna` is set. See: #127127. */
8909
8911 PyModule_GetState(submodule));
8912 BLI_assert(state->ptr.has_value());
8913
8914 PyObject *arg_key, *arg_value;
8915 Py_ssize_t arg_pos = 0;
8916 while (PyDict_Next(bpy_types_dict, &arg_pos, &arg_key, &arg_value)) {
8917 const char *key_str = PyUnicode_AsUTF8(arg_key);
8918 if (key_str[0] == '_') {
8919 continue;
8920 }
8921
8923 PyObject_IsSubclass(arg_value, (PyObject *)&pyrna_struct_Type),
8924 "Members of _bpy_types.py which are not StructRNA sub-classes must use a \"_\" prefix!");
8925
8926 PointerRNA newptr;
8927 if (RNA_property_collection_lookup_string(&state->ptr.value(), state->prop, key_str, &newptr))
8928 {
8929 StructRNA *srna = srna_from_ptr(&newptr);
8930 /* Within the Python logic of `./scripts/modules/_bpy_types.py`
8931 * it's possible this was already initialized. */
8932 if (RNA_struct_py_type_get(srna) == nullptr) {
8933 pyrna_subtype_set_rna(arg_value, srna);
8934 }
8935 }
8936#ifndef NDEBUG
8937 else {
8938 /* Avoid noisy warnings based on build-options. */
8939# ifndef WITH_USD
8940 if (STREQ(key_str, "USDHook")) {
8941 continue;
8942 }
8943# endif
8944 CLOG_WARN(
8945 BPY_LOG_RNA, "_bpy_types.py defines \"%.200s\" which is not a known RNA type!", key_str);
8946 }
8947#endif
8948 }
8949}
8950
8952
8953/* -------------------------------------------------------------------- */
8958
8959StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix)
8960{
8961 BPy_StructRNA *py_srna = nullptr;
8962 StructRNA *srna;
8963
8964 /* Unfortunately PyObject_GetAttrString won't look up this types tp_dict first :/ */
8965 if (PyType_Check(self)) {
8966 py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)self)->tp_dict,
8968 Py_XINCREF(py_srna);
8969 }
8970
8971 if (parent) {
8972 /* be very careful with this since it will return a parent classes srna.
8973 * modifying this will do confusing stuff! */
8974 if (py_srna == nullptr) {
8975 py_srna = (BPy_StructRNA *)PyObject_GetAttr(self, bpy_intern_str_bl_rna);
8976 }
8977 }
8978
8979 if (py_srna == nullptr) {
8980 PyErr_Format(PyExc_RuntimeError,
8981 "%.200s, missing bl_rna attribute from '%.200s' instance (may not be registered)",
8982 error_prefix,
8983 Py_TYPE(self)->tp_name);
8984 return nullptr;
8985 }
8986
8987 if (!BPy_StructRNA_Check(py_srna)) {
8988 PyErr_Format(PyExc_TypeError,
8989 "%.200s, bl_rna attribute wrong type '%.200s' on '%.200s'' instance",
8990 error_prefix,
8991 Py_TYPE(py_srna)->tp_name,
8992 Py_TYPE(self)->tp_name);
8993 Py_DECREF(py_srna);
8994 return nullptr;
8995 }
8996
8997 if (py_srna->ptr->type != &RNA_Struct) {
8998 PyErr_Format(PyExc_TypeError,
8999 "%.200s, bl_rna attribute not a RNA_Struct, on '%.200s'' instance",
9000 error_prefix,
9001 Py_TYPE(self)->tp_name);
9002 Py_DECREF(py_srna);
9003 return nullptr;
9004 }
9005
9006 srna = static_cast<StructRNA *>(py_srna->ptr->data);
9007 Py_DECREF(py_srna);
9008
9009 return srna;
9010}
9011
9012const PointerRNA *pyrna_struct_as_ptr(PyObject *py_obj, const StructRNA *srna)
9013{
9014 BPy_StructRNA *bpy_srna = (BPy_StructRNA *)py_obj;
9015 if (!BPy_StructRNA_Check(py_obj) || !RNA_struct_is_a(bpy_srna->ptr->type, srna)) {
9016 PyErr_Format(PyExc_TypeError,
9017 "Expected a \"bpy.types.%.200s\" not a \"%.200s\"",
9019 Py_TYPE(py_obj)->tp_name);
9020 return nullptr;
9021 }
9022 PYRNA_STRUCT_CHECK_OBJ(bpy_srna);
9023 return &bpy_srna->ptr.value();
9024}
9025
9026const PointerRNA *pyrna_struct_as_ptr_or_null(PyObject *py_obj, const StructRNA *srna)
9027{
9028 if (py_obj == Py_None) {
9029 return &PointerRNA_NULL;
9030 }
9031 return pyrna_struct_as_ptr(py_obj, srna);
9032}
9033
9034int pyrna_struct_as_ptr_parse(PyObject *o, void *p)
9035{
9036 BPy_StructRNA_Parse *srna_parse = static_cast<BPy_StructRNA_Parse *>(p);
9037 BLI_assert(srna_parse->type != nullptr);
9038 srna_parse->ptr = pyrna_struct_as_ptr(o, srna_parse->type);
9039 if (srna_parse->ptr == nullptr) {
9040 return 0;
9041 }
9042 return 1;
9043}
9044
9045int pyrna_struct_as_ptr_or_null_parse(PyObject *o, void *p)
9046{
9047 BPy_StructRNA_Parse *srna_parse = static_cast<BPy_StructRNA_Parse *>(p);
9048 BLI_assert(srna_parse->type != nullptr);
9049 srna_parse->ptr = pyrna_struct_as_ptr_or_null(o, srna_parse->type);
9050 if (srna_parse->ptr == nullptr) {
9051 return 0;
9052 }
9053 return 1;
9054}
9055
9056/* Orphan functions, not sure where they should go. */
9057
9058StructRNA *srna_from_self(PyObject *self, const char *error_prefix)
9059{
9060 if (self == nullptr) {
9061 return nullptr;
9062 }
9063 if (PyCapsule_CheckExact(self)) {
9064 return static_cast<StructRNA *>(PyCapsule_GetPointer(self, nullptr));
9065 }
9066 if (PyType_Check(self) == 0) {
9067 return nullptr;
9068 }
9069
9070 /* These cases above not errors, they just mean the type was not compatible
9071 * After this any errors will be raised in the script. */
9072 return pyrna_struct_as_srna(self, false, error_prefix);
9073}
9074
9076
9077/* -------------------------------------------------------------------- */
9080
9081static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item)
9082{
9084 /* No error, ignoring. */
9085 return 0;
9086 }
9087
9088 /* We only care about results from C which
9089 * are for sure types, save some time with error */
9090 PyObject *py_func = static_cast<PyObject *>(((BPy_PropDeferred *)item)->fn);
9091 PyObject *py_kw = ((BPy_PropDeferred *)item)->kw;
9092
9093 /* Show the function name in errors to help give context. */
9094 BLI_assert(PyCFunction_CheckExact(py_func));
9095 PyMethodDef *py_func_method_def = ((PyCFunctionObject *)py_func)->m_ml;
9096 const char *func_name = py_func_method_def->ml_name;
9097
9098 const char *key_str = PyUnicode_AsUTF8(key);
9099
9100 if (*key_str == '_') {
9101 PyErr_Format(PyExc_ValueError,
9102 "bpy_struct \"%.200s\" registration error: "
9103 "'%.200s' %.200s could not register because it starts with an '_'",
9105 key_str,
9106 func_name);
9107 return -1;
9108 }
9109
9110 PyObject *type = PyDict_GetItemString(py_kw, "type");
9111 StructRNA *type_srna = srna_from_self(type, "");
9112 if (type_srna) {
9114 PyCFunctionWithKeywords py_func_ref = *(
9115 PyCFunctionWithKeywords)(void *)PyCFunction_GET_FUNCTION(py_func);
9116 if (ELEM(py_func_ref, BPy_PointerProperty, BPy_CollectionProperty)) {
9118
9119 PyErr_Format(PyExc_ValueError,
9120 "bpy_struct \"%.200s\" registration error: "
9121 "'%.200s' %.200s could not register because "
9122 "this type doesn't support data-block properties",
9124 key_str,
9125 func_name);
9126 return -1;
9127 }
9128 }
9129 }
9130 }
9131
9132 PyObject *py_srna_cobject = PyCapsule_New(srna, nullptr, nullptr);
9133
9134 /* Not 100% nice :/, modifies the dict passed, should be ok. */
9135 PyDict_SetItem(py_kw, bpy_intern_str_attr, key);
9136
9137 PyObject *args_fake = PyTuple_New(1);
9138 PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject);
9139
9140 PyObject *py_ret = PyObject_Call(py_func, args_fake, py_kw);
9141
9142 if (py_ret) {
9143 Py_DECREF(py_ret);
9144 Py_DECREF(args_fake); /* Free's py_srna_cobject too. */
9145 }
9146 else {
9147 /* _must_ print before decrefing args_fake. */
9148 PyErr_Print();
9149
9150 Py_DECREF(args_fake); /* Free's py_srna_cobject too. */
9151
9152 PyErr_Format(PyExc_ValueError,
9153 "bpy_struct \"%.200s\" registration error: "
9154 "'%.200s' %.200s could not register (see previous error)",
9156 key_str,
9157 func_name);
9158 return -1;
9159 }
9160
9161 return 0;
9162}
9163
9167static int pyrna_deferred_register_class_from_type_hints(StructRNA *srna, PyTypeObject *py_class)
9168{
9169 PyObject *annotations_dict = nullptr;
9170
9171 /* `typing.get_type_hints(py_class)` */
9172 {
9173 PyObject *typing_mod = PyImport_ImportModuleLevel("typing", nullptr, nullptr, nullptr, 0);
9174 if (typing_mod != nullptr) {
9175 PyObject *get_type_hints_fn = PyObject_GetAttrString(typing_mod, "get_type_hints");
9176 if (get_type_hints_fn != nullptr) {
9177 PyObject *args = PyTuple_New(1);
9178
9179 PyTuple_SET_ITEM(args, 0, (PyObject *)py_class);
9180 Py_INCREF(py_class);
9181
9182 annotations_dict = PyObject_CallObject(get_type_hints_fn, args);
9183
9184 Py_DECREF(args);
9185 Py_DECREF(get_type_hints_fn);
9186 }
9187 Py_DECREF(typing_mod);
9188 }
9189 }
9190
9191 int ret = 0;
9192 if (annotations_dict != nullptr) {
9193 if (PyDict_CheckExact(annotations_dict)) {
9194 PyObject *item, *key;
9195 Py_ssize_t pos = 0;
9196
9197 while (PyDict_Next(annotations_dict, &pos, &key, &item)) {
9198 ret = deferred_register_prop(srna, key, item);
9199 if (ret != 0) {
9200 break;
9201 }
9202 }
9203 }
9204 else {
9205 /* Should never happen, an error won't have been raised, so raise one. */
9206 PyErr_Format(PyExc_TypeError,
9207 "typing.get_type_hints returned: %.200s, expected dict\n",
9208 Py_TYPE(annotations_dict)->tp_name);
9209 ret = -1;
9210 }
9211
9212 Py_DECREF(annotations_dict);
9213 }
9214 else {
9215 BLI_assert(PyErr_Occurred());
9216 fprintf(stderr, "typing.get_type_hints failed with: %.200s\n", py_class->tp_name);
9217 ret = -1;
9218 }
9219
9220 return ret;
9221}
9222
9223static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
9224{
9225 PyObject *annotations_dict;
9226 PyObject *item, *key;
9227 Py_ssize_t pos = 0;
9228 int ret = 0;
9229
9230 /* in both cases PyDict_CheckExact(class_dict) will be true even
9231 * though Operators have a metaclass dict namespace */
9232 if ((annotations_dict = PyDict_GetItem(class_dict, bpy_intern_str___annotations__)) &&
9233 PyDict_CheckExact(annotations_dict))
9234 {
9235 while (PyDict_Next(annotations_dict, &pos, &key, &item)) {
9236 ret = deferred_register_prop(srna, key, item);
9237
9238 if (ret != 0) {
9239 break;
9240 }
9241 }
9242 }
9243
9244 return ret;
9245}
9246
9247static int pyrna_deferred_register_class_recursive(StructRNA *srna, PyTypeObject *py_class)
9248{
9249 const int len = PyTuple_GET_SIZE(py_class->tp_bases);
9250 int i, ret;
9251
9252 /* First scan base classes for registerable properties. */
9253 for (i = 0; i < len; i++) {
9254 PyTypeObject *py_superclass = (PyTypeObject *)PyTuple_GET_ITEM(py_class->tp_bases, i);
9255
9256 /* the rules for using these base classes are not clear,
9257 * 'object' is of course not worth looking into and
9258 * existing subclasses of RNA would cause a lot more dictionary
9259 * looping then is needed (SomeOperator would scan Operator.__dict__)
9260 * which is harmless, but not at all useful.
9261 *
9262 * So only scan base classes which are not subclasses if blender types.
9263 * This best fits having 'mix-in' classes for operators and render engines.
9264 */
9265 if (py_superclass != &PyBaseObject_Type &&
9266 !PyObject_IsSubclass((PyObject *)py_superclass, (PyObject *)&pyrna_struct_Type))
9267 {
9268 ret = pyrna_deferred_register_class_recursive(srna, py_superclass);
9269
9270 if (ret != 0) {
9271 return ret;
9272 }
9273 }
9274 }
9275
9276 /* Not register out own properties. */
9277 /* getattr(..., "__dict__") returns a proxy. */
9278 return pyrna_deferred_register_props(srna, py_class->tp_dict);
9279}
9280
9281int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class)
9282{
9283 /* Panels and Menus don't need this
9284 * save some time and skip the checks here */
9286 return 0;
9287 }
9288
9289#ifdef USE_POSTPONED_ANNOTATIONS
9290 const bool use_postponed_annotations = true;
9291#else
9292 const bool use_postponed_annotations = false;
9293#endif
9294
9295 if (use_postponed_annotations) {
9296 return pyrna_deferred_register_class_from_type_hints(srna, py_class);
9297 }
9298 return pyrna_deferred_register_class_recursive(srna, py_class);
9299}
9300
9301static int rna_function_register_arg_count(FunctionRNA *func, int *min_count)
9302{
9303 const ListBase *lb = RNA_function_defined_parameters(func);
9304 PropertyRNA *parm;
9305 const int flag = RNA_function_flag(func);
9306 const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
9307 int count = is_staticmethod ? 0 : 1;
9308 bool done_min_count = false;
9309
9310 LISTBASE_FOREACH (Link *, link, lb) {
9311 parm = (PropertyRNA *)link;
9312 if (!(RNA_parameter_flag(parm) & PARM_OUTPUT)) {
9313 if (!done_min_count && (RNA_parameter_flag(parm) & PARM_PYFUNC_REGISTER_OPTIONAL)) {
9314 /* From now on, the following parameters are optional in a Python function. */
9315 if (min_count) {
9316 *min_count = count;
9317 }
9318 done_min_count = true;
9319 }
9320 count++;
9321 }
9322 }
9323
9324 if (!done_min_count && min_count) {
9325 *min_count = count;
9326 }
9327 return count;
9328}
9329
9331
9332/* -------------------------------------------------------------------- */
9337
9339 StructRNA *srna,
9340 void *py_data,
9341 bool *have_function)
9342{
9343 const ListBase *lb;
9344 const char *class_type = RNA_struct_identifier(srna);
9345 StructRNA *srna_base = RNA_struct_base(srna);
9346 PyObject *py_class = (PyObject *)py_data;
9347 PyObject *base_class = static_cast<PyObject *>(RNA_struct_py_type_get(srna));
9348 int i, arg_count, func_arg_count, func_arg_min_count = 0;
9349 const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */
9350
9351 if (srna_base) {
9352 if (bpy_class_validate_recursive(dummy_ptr, srna_base, py_data, have_function) != 0) {
9353 return -1;
9354 }
9355 }
9356
9357 if (base_class) {
9358 if (!PyObject_IsSubclass(py_class, base_class)) {
9359 PyErr_Format(PyExc_TypeError,
9360 "expected %.200s subclass of class \"%.200s\"",
9361 class_type,
9362 py_class_name);
9363 return -1;
9364 }
9365 }
9366
9367 /* Verify callback functions. */
9368 lb = RNA_struct_type_functions(srna);
9369 i = 0;
9370 LISTBASE_FOREACH (Link *, link, lb) {
9371 FunctionRNA *func = (FunctionRNA *)link;
9372 const int flag = RNA_function_flag(func);
9373 if (!(flag & FUNC_REGISTER)) {
9374 continue;
9375 }
9376
9377 PyObject *item;
9378 switch (PyObject_GetOptionalAttrString(py_class, RNA_function_identifier(func), &item)) {
9379 case 1: {
9380 break;
9381 }
9382 case 0: {
9383 if ((flag & (FUNC_REGISTER_OPTIONAL & ~FUNC_REGISTER)) == 0) {
9384 PyErr_Format(PyExc_AttributeError,
9385 "expected %.200s, %.200s class to have an \"%.200s\" attribute",
9386 class_type,
9387 py_class_name,
9389 return -1;
9390 }
9391 break;
9392 }
9393 case -1: { /* Unexpected error, an exception will have been raise. */
9394 return -1;
9395 }
9396 }
9397
9398 have_function[i] = (item != nullptr);
9399 i++;
9400
9401 if (item == nullptr) {
9402 continue;
9403 }
9404
9405 /* TODO(@ideasman42): this is used for classmethod's too,
9406 * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg.
9407 * Keep this as-is since it's working, but we should be using
9408 * 'FUNC_USE_SELF_TYPE' for many functions. */
9409 const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
9410
9411 /* Store original so we can decrement its reference before returning. */
9412 PyObject *item_orig = item;
9413
9414 if (is_staticmethod) {
9415 if (PyMethod_Check(item) == 0) {
9416 PyErr_Format(PyExc_TypeError,
9417 "expected %.200s, %.200s class \"%.200s\" "
9418 "attribute to be a static/class method, not a %.200s",
9419 class_type,
9420 py_class_name,
9422 Py_TYPE(item)->tp_name);
9423 Py_DECREF(item_orig);
9424 return -1;
9425 }
9426 item = ((PyMethodObject *)item)->im_func;
9427 }
9428 else {
9429 if (PyFunction_Check(item) == 0) {
9430 PyErr_Format(PyExc_TypeError,
9431 "expected %.200s, %.200s class \"%.200s\" "
9432 "attribute to be a function, not a %.200s",
9433 class_type,
9434 py_class_name,
9436 Py_TYPE(item)->tp_name);
9437 Py_DECREF(item_orig);
9438 return -1;
9439 }
9440 }
9441
9442 func_arg_count = rna_function_register_arg_count(func, &func_arg_min_count);
9443
9444 if (func_arg_count >= 0) { /* -1 if we don't care. */
9445 arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
9446
9447 /* NOTE: the number of args we check for and the number of args we give to
9448 * `@staticmethods` are different (quirk of Python),
9449 * this is why #rna_function_register_arg_count() doesn't return the value -1. */
9450 if (is_staticmethod) {
9451 func_arg_count++;
9452 func_arg_min_count++;
9453 }
9454
9455 if (arg_count < func_arg_min_count || arg_count > func_arg_count) {
9456 if (func_arg_min_count != func_arg_count) {
9457 PyErr_Format(
9458 PyExc_ValueError,
9459 "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d "
9460 "args, found %d",
9461 class_type,
9462 py_class_name,
9464 func_arg_count,
9465 func_arg_min_count,
9466 arg_count);
9467 }
9468 else {
9469 PyErr_Format(
9470 PyExc_ValueError,
9471 "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d",
9472 class_type,
9473 py_class_name,
9475 func_arg_count,
9476 arg_count);
9477 }
9478 Py_DECREF(item_orig);
9479 return -1;
9480 }
9481 }
9482 Py_DECREF(item_orig);
9483 }
9484
9485 /* Allow Python `__name__` to be used for `bl_idname` for convenience. */
9486 struct {
9487 const char *rna_attr;
9488 PyObject *py_attr;
9489 } bpy_property_substitutions[] = {
9490 {"bl_idname", bpy_intern_str___name__},
9491 {"bl_description", bpy_intern_str___doc__},
9492 };
9493
9494 /* Verify properties. */
9495 lb = RNA_struct_type_properties(srna);
9496 LISTBASE_FOREACH (Link *, link, lb) {
9497 PropertyRNA *prop = (PropertyRNA *)link;
9498 const int flag = RNA_property_flag(prop);
9499
9500 if (!(flag & PROP_REGISTER)) {
9501 continue;
9502 }
9503
9504 const char *identifier = RNA_property_identifier(prop);
9505 PyObject *item = nullptr;
9506 switch (PyObject_GetOptionalAttrString(py_class, identifier, &item)) {
9507 case 1: { /* Found. */
9508 if (pyrna_py_to_prop(dummy_ptr, prop, nullptr, item, "validating class:") != 0) {
9509 Py_DECREF(item);
9510 return -1;
9511 }
9512 Py_DECREF(item);
9513 break;
9514 }
9515 case -1: { /* Not found (an unexpected error). */
9516 /* Typically the attribute will exist or not, in previous releases all errors
9517 * were assumed to be missing attributes, so print the error and move on. */
9518 PyErr_Print();
9519 [[fallthrough]];
9520 }
9521 case 0: { /* Not found, check for fallbacks. */
9522
9523 /* Sneaky workaround to use the class name as the `bl_idname`. */
9524 int i;
9525 for (i = 0; i < ARRAY_SIZE(bpy_property_substitutions); i += 1) {
9526 if (STREQ(identifier, bpy_property_substitutions[i].rna_attr)) {
9527 break;
9528 }
9529 }
9530
9531 if (i < ARRAY_SIZE(bpy_property_substitutions)) {
9532 PyObject *py_attr = bpy_property_substitutions[i].py_attr;
9533 switch (PyObject_GetOptionalAttr(py_class, py_attr, &item)) {
9534 case 1: { /* Found. */
9535 if (UNLIKELY(item == Py_None)) {
9536 Py_DECREF(item);
9537 item = nullptr;
9538 }
9539 else {
9540 if (pyrna_py_to_prop(dummy_ptr, prop, nullptr, item, "validating class:") != 0) {
9541 Py_DECREF(item);
9542 return -1;
9543 }
9544 Py_DECREF(item);
9545 }
9546 break;
9547 }
9548 case -1: { /* Not found (an unexpected error). */
9549 PyErr_Print();
9550 break;
9551 }
9552 }
9553 }
9554
9555 if (item == nullptr && ((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL)) {
9556 PyErr_Format(PyExc_AttributeError,
9557 "expected %.200s, %.200s class to have an \"%.200s\" attribute",
9558 class_type,
9559 py_class_name,
9560 identifier);
9561 return -1;
9562 }
9563 break;
9564 }
9565 }
9566 }
9567
9568 return 0;
9569}
9570
9571static int bpy_class_validate(PointerRNA *dummy_ptr, void *py_data, bool *have_function)
9572{
9573 return bpy_class_validate_recursive(dummy_ptr, dummy_ptr->type, py_data, have_function);
9574}
9575
9576/* TODO: multiple return values like with RNA functions. */
9578{
9579 PyObject *args;
9580 PyObject *ret = nullptr, *py_srna = nullptr, *py_class_instance = nullptr, *parmitem;
9581 PyTypeObject *py_class;
9582 PropertyRNA *parm;
9583 ParameterIterator iter;
9584 PointerRNA funcptr;
9585 int err = 0, i, ret_len = 0;
9586 const int flag = RNA_function_flag(func);
9587 const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
9588 const bool is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE);
9589
9590 PropertyRNA *pret_single = nullptr;
9591 void *retdata_single = nullptr;
9592
9593 PyGILState_STATE gilstate;
9594
9595#ifdef USE_PEDANTIC_WRITE
9596 const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) ||
9597 RNA_struct_is_a(ptr->type, &RNA_Gizmo));
9598 // const char *func_id = RNA_function_identifier(func); /* UNUSED */
9599 /* Testing, for correctness, not operator and not draw function. */
9600 const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE);
9601#endif
9602
9603 py_class = static_cast<PyTypeObject *>(RNA_struct_py_type_get(ptr->type));
9604 /* Rare case. can happen when registering subclasses. */
9605 if (py_class == nullptr) {
9607 "unable to get Python class for RNA struct '%.200s'",
9608 RNA_struct_identifier(ptr->type));
9609 return -1;
9610 }
9611
9612 /* XXX, this is needed because render engine calls without a context
9613 * this should be supported at some point, but at the moment it's not! */
9614 if (C == nullptr) {
9615 C = BPY_context_get();
9616 }
9617
9618 bpy_context_set(C, &gilstate);
9619
9620 /* Annoying! We need to check if the screen gets set to nullptr which is a
9621 * hint that the file was actually re-loaded. */
9622 const bool is_valid_wm = (CTX_wm_manager(C) != nullptr);
9623
9624 if (!(is_staticmethod || is_classmethod)) {
9625 /* Some data-types (operator, render engine) can store PyObjects for re-use. */
9626 if (ptr->data) {
9627 void **instance = RNA_struct_instance(ptr);
9628
9629 if (instance) {
9630 if (*instance) {
9631 py_class_instance = static_cast<PyObject *>(*instance);
9632 Py_INCREF(py_class_instance);
9633 }
9634 }
9635 }
9636 /* End exception. */
9637
9638 if (py_class_instance == nullptr) {
9640 }
9641
9642 if (py_class_instance) {
9643 /* Special case, instance is cached. */
9644 }
9645 else if (py_srna == nullptr) {
9646 py_class_instance = nullptr;
9647 if (PyErr_Occurred()) {
9648 err = -1; /* So the error is not overridden below. */
9649 }
9650 }
9651 else if (py_srna == Py_None) { /* Probably won't ever happen, but possible. */
9652 Py_DECREF(py_srna);
9653 py_class_instance = nullptr;
9654 if (PyErr_Occurred()) {
9655 err = -1; /* So the error is not overridden below. */
9656 }
9657 }
9658 else {
9659#if 0
9660 /* Skip the code below and call init directly on the allocated 'py_srna'
9661 * otherwise __init__() always needs to take a second self argument, see pyrna_struct_new().
9662 * Although this is annoying to have to implement a part of Python's
9663 * typeobject.c:type_call().
9664 */
9665 if (py_class->tp_init) {
9666# ifdef USE_PEDANTIC_WRITE
9667 const int prev_write = rna_disallow_writes;
9668 rna_disallow_writes = is_readonly_init ? false :
9669 true; /* Only operators can write on __init__. */
9670# endif
9671
9672 /* True in most cases even when the class itself doesn't define an __init__ function. */
9673 args = PyTuple_New(0);
9674 if (py_class->tp_init(py_srna, args, nullptr) < 0) {
9675 Py_DECREF(py_srna);
9676 py_srna = nullptr;
9677 /* Err set below. */
9678 }
9679 Py_DECREF(args);
9680# ifdef USE_PEDANTIC_WRITE
9681 rna_disallow_writes = prev_write;
9682# endif
9683 }
9684 py_class_instance = py_srna;
9685
9686#else
9687# ifdef USE_PEDANTIC_WRITE
9688 const int prev_write = rna_disallow_writes;
9689 rna_disallow_writes = is_readonly_init ? false :
9690 true; /* Only operators can write on __init__. */
9691# endif
9692
9693/* 'almost' all the time calling the class isn't needed.
9694 * We could just do... */
9695# if 0
9696 py_class_instance = py_srna;
9697 Py_INCREF(py_class_instance);
9698# endif
9699 /*
9700 * This would work fine, but means __init__ functions wouldn't run.
9701 * None of Blender's default scripts use __init__ but it's nice to call it
9702 * for general correctness. just to note why this is here when it could be safely removed.
9703 */
9704 py_class_instance = PyObject_CallOneArg(reinterpret_cast<PyObject *>(py_class), py_srna);
9705
9706# ifdef USE_PEDANTIC_WRITE
9707 rna_disallow_writes = prev_write;
9708# endif
9709
9710#endif
9711
9712 if (py_class_instance == nullptr) {
9713 if (PyErr_Occurred()) {
9714 err = -1; /* So the error is not overridden below. */
9715 }
9716 }
9717
9718 Py_DECREF(py_srna);
9719 }
9720 }
9721
9722 /* Initializing the class worked, now run its invoke function. */
9723 if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) {
9724 PyObject *item = PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func));
9725
9726 const bool item_type_valid = (item != nullptr) &&
9727 (is_staticmethod ? PyMethod_Check(item) : PyFunction_Check(item));
9728 if (item_type_valid) {
9729 funcptr = RNA_pointer_create_discrete(nullptr, &RNA_Function, func);
9730 int arg_count;
9731
9732 /* NOTE: registration will have already checked the argument count matches
9733 * #rna_function_register_arg_count so there is no need to inspect the RNA function. */
9734
9735 if (is_staticmethod) {
9736 arg_count =
9737 ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount -
9738 1;
9739 }
9740 else {
9741 arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
9742 }
9743 args = PyTuple_New(arg_count); /* First arg is included in 'item'. */
9744
9745 if (is_staticmethod) {
9746 i = 0;
9747 }
9748 else if (is_classmethod) {
9749 PyTuple_SET_ITEM(args, 0, (PyObject *)py_class);
9750 i = 1;
9751 }
9752 else {
9753 PyTuple_SET_ITEM(args, 0, py_class_instance);
9754 i = 1;
9755 }
9756
9757 RNA_parameter_list_begin(parms, &iter);
9758
9759 /* Parse function parameters. */
9760 for (; iter.valid; RNA_parameter_list_next(&iter)) {
9761 parm = iter.parm;
9762
9763 /* Only useful for single argument returns, we'll need another list loop for multiple. */
9764 if (RNA_parameter_flag(parm) & PARM_OUTPUT) {
9765 ret_len++;
9766 if (pret_single == nullptr) {
9767 pret_single = parm;
9768 retdata_single = iter.data;
9769 }
9770
9771 continue;
9772 }
9773
9774 if (i < arg_count) {
9775 parmitem = pyrna_param_to_py(&funcptr, parm, iter.data);
9776 PyTuple_SET_ITEM(args, i, parmitem);
9777 i++;
9778 }
9779 }
9780
9781#ifdef USE_PEDANTIC_WRITE
9782 /* Handle nested draw calls, see: #89253. */
9783 const bool rna_disallow_writes_prev = rna_disallow_writes;
9784 rna_disallow_writes = is_readonly ? true : false;
9785#endif
9786 /* *** Main Caller *** */
9787
9788 ret = PyObject_Call(item, args, nullptr);
9789
9790 /* *** Done Calling *** */
9791
9792#ifdef USE_PEDANTIC_WRITE
9793 rna_disallow_writes = rna_disallow_writes_prev;
9794#endif
9795
9797 Py_DECREF(item);
9798 Py_DECREF(args);
9799 }
9800 else {
9801 PyErr_Print();
9802 PyErr_Format(PyExc_TypeError,
9803 "could not find function %.200s in %.200s to execute callback",
9805 RNA_struct_identifier(ptr->type));
9806 err = -1;
9807 }
9808 }
9809 else {
9810 /* The error may be already set if the class instance couldn't be created. */
9811 if (err != -1) {
9812 PyErr_Format(PyExc_RuntimeError,
9813 "could not create instance of %.200s to call callback function '%.200s'",
9816 err = -1;
9817 }
9818 }
9819
9820 if (ret == nullptr) { /* Covers py_class_instance failing too. */
9821 err = -1;
9822 }
9823 else {
9824 if (ret_len == 0 && ret != Py_None) {
9825 PyErr_Format(PyExc_RuntimeError,
9826 "expected class %.200s, function %.200s to return None, not %.200s",
9829 Py_TYPE(ret)->tp_name);
9830 err = -1;
9831 }
9832 else if (ret_len == 1) {
9833 err = pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "");
9834
9835 /* When calling operator functions only gives `Function.result` with no line number
9836 * since the function has finished calling on error, re-raise the exception with more
9837 * information since it would be slow to create prefix on every call
9838 * (when there are no errors). */
9839 if (err == -1) {
9840 PyC_Err_Format_Prefix(PyExc_RuntimeError,
9841 "class %.200s, function %.200s: incompatible return value ",
9844 }
9845 }
9846 else if (ret_len > 1) {
9847
9848 if (PyTuple_Check(ret) == 0) {
9849 PyErr_Format(
9850 PyExc_RuntimeError,
9851 "expected class %.200s, function %.200s to return a tuple of size %d, not %.200s",
9854 ret_len,
9855 Py_TYPE(ret)->tp_name);
9856 err = -1;
9857 }
9858 else if (PyTuple_GET_SIZE(ret) != ret_len) {
9859 PyErr_Format(PyExc_RuntimeError,
9860 "class %.200s, function %.200s to returned %d items, expected %d",
9863 PyTuple_GET_SIZE(ret),
9864 ret_len);
9865 err = -1;
9866 }
9867 else {
9868
9869 RNA_parameter_list_begin(parms, &iter);
9870
9871 /* Parse function parameters. */
9872 for (i = 0; iter.valid; RNA_parameter_list_next(&iter)) {
9873 parm = iter.parm;
9874
9875 /* Only useful for single argument returns, we'll need another list loop for multiple. */
9876 if (RNA_parameter_flag(parm) & PARM_OUTPUT) {
9877 err = pyrna_py_to_prop(
9878 &funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:");
9879 if (err) {
9880 break;
9881 }
9882 }
9883 }
9884
9886 }
9887 }
9888 Py_DECREF(ret);
9889 }
9890
9891 if (err != 0) {
9892 ReportList *reports;
9893 /* Alert the user, else they won't know unless they see the console. */
9894 if ((!is_staticmethod) && (!is_classmethod) && (ptr->data) &&
9895 RNA_struct_is_a(ptr->type, &RNA_Operator) &&
9896 (is_valid_wm == (CTX_wm_manager(C) != nullptr)))
9897 {
9898 wmOperator *op = static_cast<wmOperator *>(ptr->data);
9899 reports = op->reports;
9900 }
9901 else {
9902 /* Won't alert users, but they can view in 'info' space. */
9903 reports = CTX_wm_reports(C);
9904 }
9905
9906 if (reports) {
9907 BPy_errors_to_report(reports);
9908 }
9909
9910 /* Also print in the console for Python. */
9911 PyErr_Print();
9912 /* Print a small line at ERROR level so that tests that rely on --debug-exit-on-error can
9913 * fail. This assumes that the majority of the information is already seen in the console via
9914 * PyErr_Print and should not be duplicated */
9916 "Python script error in %.200s.%.200s",
9919 }
9920
9921 bpy_context_clear(C, &gilstate);
9922
9923 return err;
9924}
9925
9929static void bpy_class_free_ex(PyObject *self, bool decref)
9930{
9931#ifdef WITH_PYTHON_MODULE
9932 /* This can happen when Python has exited before all Blender's RNA types have been freed.
9933 * In this Python memory management can't run.
9934 *
9935 * NOTE(@ideasman42): While I wasn't able to redo locally, it resolves the problem.
9936 * This happens:
9937 * - With AUDASPACE on macOS, see: #125376.
9938 * - With the build-bot on Linux, see: #135195.
9939 * Ideally this would be resolved
9940 * by correcting the order classes are freed (before Python exits). */
9941 if (!Py_IsInitialized()) {
9942 return;
9943 }
9944#endif
9945
9946 PyGILState_STATE gilstate = PyGILState_Ensure();
9947
9948 /* Breaks re-registering classes. */
9949 // PyDict_Clear(((PyTypeObject *)self)->tp_dict);
9950
9951 /* Remove the RNA attribute instead. */
9952
9953 /* NOTE: it's important to use `delattr` instead of `PyDict_DelItem`
9954 * to ensure the internal slots are updated (which is also used for assignment). */
9955 if (PyObject_DelAttr(self, bpy_intern_str_bl_rna) == -1) {
9956 PyErr_Clear();
9957 }
9958
9959#if 0 /* Needs further investigation, too annoying so quiet for now. */
9960 if (G.debug & G_DEBUG_PYTHON) {
9961 if (self->ob_refcnt > 1) {
9962 PyC_ObSpit("zombie class - reference should be 1", self);
9963 }
9964 }
9965#endif
9966
9967 if (decref) {
9968 Py_DECREF(self);
9969 }
9970
9971 PyGILState_Release(gilstate);
9972}
9973
9974static void bpy_class_free(void *pyob_ptr)
9975{
9976 /* Don't remove a reference because the argument passed in is from #ExtensionRNA::data
9977 * which doesn't own the reference.
9978 * This value is typically stored in #StructRNA::py_type which is handled separately. */
9979 bool decref = false;
9980 bpy_class_free_ex(static_cast<PyObject *>(pyob_ptr), decref);
9981}
9982
9986static PyTypeObject *bpy_class_check_any_bases_registered(PyTypeObject *cls)
9987{
9988 if (PyObject *bases = cls->tp_bases) {
9989 const int bases_num = PyTuple_GET_SIZE(bases);
9990 for (int i = 0; i < bases_num; i++) {
9991 PyTypeObject *base_cls = (PyTypeObject *)PyTuple_GET_ITEM(bases, i);
9992 BLI_assert(PyType_Check(base_cls));
9993 if (base_cls->tp_dict) {
9994 if (BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(base_cls->tp_dict,
9996 {
9997 if (const StructRNA *srna = static_cast<const StructRNA *>(py_srna->ptr->data)) {
9998 if (srna->flag & STRUCT_RUNTIME) {
9999 return base_cls;
10000 }
10001 }
10002 }
10003 }
10004
10005 if (PyTypeObject *base_cls_test = bpy_class_check_any_bases_registered(base_cls)) {
10006 return base_cls_test;
10007 }
10008 }
10009 }
10010 return nullptr;
10011}
10012
10016static PyTypeObject *bpy_class_check_any_subclasses_registered(PyTypeObject *cls)
10017{
10018 PyObject *subclasses = static_cast<PyObject *>(cls->tp_subclasses);
10019 if (subclasses) {
10020 BLI_assert(PyDict_CheckExact(subclasses));
10021 PyObject *key = nullptr;
10022 Py_ssize_t pos = 0;
10023 PyObject *value = nullptr;
10024 while (PyDict_Next(subclasses, &pos, &key, &value)) {
10025 BLI_assert(PyWeakref_CheckRef(value));
10026 PyObject *value_ref = PyWeakref_GET_OBJECT(value);
10027 if (value_ref == Py_None) {
10028 continue;
10029 }
10030
10031 PyTypeObject *sub_cls = reinterpret_cast<PyTypeObject *>(value_ref);
10032 if (sub_cls->tp_dict) {
10033 if (BPy_StructRNA *py_srna = reinterpret_cast<BPy_StructRNA *>(
10034 PyDict_GetItem(sub_cls->tp_dict, bpy_intern_str_bl_rna)))
10035 {
10036 if (const StructRNA *srna = static_cast<const StructRNA *>(py_srna->ptr->data)) {
10037 if (srna->flag & STRUCT_RUNTIME) {
10038 return sub_cls;
10039 }
10040 }
10041 }
10042 }
10043
10044 if (PyTypeObject *sub_cls_test = bpy_class_check_any_subclasses_registered(sub_cls)) {
10045 return sub_cls_test;
10046 }
10047 }
10048 }
10049 return nullptr;
10050}
10051
10053{
10054 /* NOTE: This isn't essential to run on startup, since sub-types will lazy initialize.
10055 * But keep running in debug mode so we get immediate notification of bad class hierarchy
10056 * or any errors in `_bpy_types.py` at load time, so errors don't go unnoticed. */
10057
10058#ifndef NDEBUG
10059 PyGILState_STATE gilstate = PyGILState_Ensure();
10060
10061 PropertyRNA *prop;
10062
10063 /* Avoid doing this lookup for every getattr. */
10065 prop = RNA_struct_find_property(&ptr, "structs");
10066
10067 RNA_PROP_BEGIN (&ptr, itemptr, prop) {
10068 PyObject *item = pyrna_struct_Subtype(&itemptr);
10069 if (item == nullptr) {
10070 if (PyErr_Occurred()) {
10071 PyErr_Print();
10072 }
10073 }
10074 else {
10075 Py_DECREF(item);
10076 }
10077 }
10079
10080 PyGILState_Release(gilstate);
10081#endif /* !NDEBUG */
10082}
10083
10085{
10086 PyObject *py_ptr = static_cast<PyObject *>(RNA_struct_py_type_get(srna));
10087
10088 if (py_ptr) {
10089 /* Remove a reference because `srna` owns it. */
10090 bool decref = true;
10091 bpy_class_free_ex(py_ptr, decref);
10092 RNA_struct_py_type_set(srna, nullptr);
10093 }
10094}
10095
10096/* -------------------------------------------------------------------- */
10099
10100#define BPY_TYPEDEF_REGISTERABLE_DOC \
10101 "type[" \
10102 ":class:`bpy.types.Panel` | " \
10103 ":class:`bpy.types.UIList` | " \
10104 ":class:`bpy.types.Menu` | " \
10105 ":class:`bpy.types.Header` | " \
10106 ":class:`bpy.types.Operator` | " \
10107 ":class:`bpy.types.KeyingSetInfo` | " \
10108 ":class:`bpy.types.RenderEngine` | " \
10109 ":class:`bpy.types.AssetShelf` | " \
10110 ":class:`bpy.types.FileHandler` | " \
10111 ":class:`bpy.types.PropertyGroup` | " \
10112 ":class:`bpy.types.AddonPreferences` | " \
10113 ":class:`bpy.types.NodeTree` | " \
10114 ":class:`bpy.types.Node` | " \
10115 ":class:`bpy.types.NodeSocket`" \
10116 "]"
10117
10130 /* Wrap. */
10131 pyrna_register_class_doc,
10132 ".. function:: register_class(cls)\n"
10133 "\n"
10134 " Register a subclass of a Blender type class.\n"
10135 "\n"
10136 " :arg cls: Registerable Blender class type.\n"
10137 " :type cls: " BPY_TYPEDEF_REGISTERABLE_DOC
10138 "\n"
10139 "\n"
10140 " :raises ValueError:\n"
10141 " if the class is not a subclass of a registerable blender class.\n"
10142 "\n"
10143 " .. note::\n"
10144 "\n"
10145 " If the class has a *register* class method it will be called\n"
10146 " before registration.\n");
10148 "register_class", pyrna_register_class, METH_O, pyrna_register_class_doc};
10149static PyObject *pyrna_register_class(PyObject * /*self*/, PyObject *py_class)
10150{
10151 bContext *C = nullptr;
10152 ReportList reports;
10154 StructRNA *srna;
10155 StructRNA *srna_new;
10156 const char *identifier;
10157 PyObject *py_cls_meth;
10158 const char *error_prefix = "register_class(...):";
10159
10160 if (!PyType_Check(py_class)) {
10161 PyErr_Format(PyExc_ValueError,
10162 "%s expected a class argument, not '%.200s'",
10163 error_prefix,
10164 Py_TYPE(py_class)->tp_name);
10165 return nullptr;
10166 }
10167
10168 if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) {
10169 PyErr_Format(PyExc_ValueError,
10170 "%s already registered as a subclass '%.200s'",
10171 error_prefix,
10172 ((PyTypeObject *)py_class)->tp_name);
10173 return nullptr;
10174 }
10175
10176 if (!pyrna_write_check()) {
10177 PyErr_Format(PyExc_RuntimeError,
10178 "%s cannot run in readonly state '%.200s'",
10179 error_prefix,
10180 ((PyTypeObject *)py_class)->tp_name);
10181 return nullptr;
10182 }
10183
10184 /* WARNING: gets parent classes srna, only for the register function. */
10185 srna = pyrna_struct_as_srna(py_class, true, "register_class(...):");
10186 if (srna == nullptr) {
10187 return nullptr;
10188 }
10189
10190 if (UNLIKELY(G.debug & G_DEBUG_PYTHON)) {
10191 /* Warn if a class being registered uses an already registered base-class or sub-class,
10192 * both checks are needed otherwise the order of registering could suppress the warning.
10193 *
10194 * NOTE(@ideasman42) This is mainly to ensure good practice.
10195 * Mix-in classes are preferred when sharing functionality is needed,
10196 * otherwise changes to an Operator for example could unintentionally
10197 * break another operator that sub-classes it. */
10198 if (PyTypeObject *base_cls_test = bpy_class_check_any_bases_registered(
10199 (PyTypeObject *)py_class))
10200 {
10201 fprintf(stderr,
10202 "%s warning, %.200s: references and already registered base-class %.200s\n",
10203 error_prefix,
10204 ((PyTypeObject *)py_class)->tp_name,
10205 base_cls_test->tp_name);
10206 }
10207 if (PyTypeObject *sub_cls_test = bpy_class_check_any_subclasses_registered(
10208 (PyTypeObject *)py_class))
10209 {
10210 fprintf(stderr,
10211 "%s warning, %.200s: references and already registered sub-class %.200s\n",
10212 error_prefix,
10213 ((PyTypeObject *)py_class)->tp_name,
10214 sub_cls_test->tp_name);
10215 }
10216
10217 /* In practice it isn't useful to manipulate Python properties for `PropertyGroup`
10218 * instances since the Python objects themselves are not shared,
10219 * meaning a new Python instance is returned on each attribute access.
10220 * It may be useful to include other classes in this check - extend as needed.
10221 * See #141948. */
10222 if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
10223 if (!PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str___slots__)) {
10224 fprintf(stderr,
10225 "%s warning, %.200s: is expected to contain a \"__slots__\" member "
10226 "to prevent arbitrary assignments.\n",
10227 error_prefix,
10228 ((PyTypeObject *)py_class)->tp_name);
10229 }
10230 }
10231 }
10232
10233/* Fails in some cases, so can't use this check, but would like to :| */
10234#if 0
10235 if (RNA_struct_py_type_get(srna)) {
10236 PyErr_Format(PyExc_ValueError,
10237 "%s %.200s's parent class %.200s is already registered, this is not allowed",
10238 error_prefix,
10239 ((PyTypeObject *)py_class)->tp_name,
10240 RNA_struct_identifier(srna));
10241 return nullptr;
10242 }
10243#endif
10244
10245 /* Check that we have a register callback for this type. */
10246 reg = RNA_struct_register(srna);
10247
10248 if (!reg) {
10249 PyErr_Format(PyExc_ValueError,
10250 "%s expected a subclass of a registerable "
10251 "RNA type (%.200s does not support registration)",
10252 error_prefix,
10253 RNA_struct_identifier(srna));
10254 return nullptr;
10255 }
10256
10257 /* Get the context, so register callback can do necessary refreshes. */
10258 C = BPY_context_get();
10259
10260 /* Call the register callback with reports & identifier. */
10262
10263 identifier = ((PyTypeObject *)py_class)->tp_name;
10264
10265 srna_new = reg(CTX_data_main(C),
10266 &reports,
10267 py_class,
10268 identifier,
10272
10273 if (!BLI_listbase_is_empty(&reports.list)) {
10274 const bool has_error = (BPy_reports_to_error(&reports, PyExc_RuntimeError, false) == -1);
10275 if (!has_error) {
10277 BPy_reports_write_stdout(&reports, error_prefix);
10278 }
10279 if (has_error) {
10280 BKE_reports_free(&reports);
10281 return nullptr;
10282 }
10283 }
10284 BKE_reports_free(&reports);
10285
10286 /* Python errors validating are not converted into reports so the check above will fail.
10287 * the cause for returning nullptr will be printed as an error */
10288 if (srna_new == nullptr) {
10289 return nullptr;
10290 }
10291
10292 /* Takes a reference to 'py_class'. */
10293 pyrna_subtype_set_rna(py_class, srna_new);
10294
10295 /* Old srna still references us, keep the check in case registering somehow can free it. */
10296 if (PyObject *old_py_class = static_cast<PyObject *>(RNA_struct_py_type_get(srna))) {
10297 RNA_struct_py_type_set(srna, nullptr);
10298 Py_DECREF(old_py_class);
10299 }
10300
10301 /* Can't use this because it returns a dict proxy
10302 *
10303 * item = PyObject_GetAttrString(py_class, "__dict__");
10304 */
10305 if (pyrna_deferred_register_class(srna_new, (PyTypeObject *)py_class) != 0) {
10306 return nullptr;
10307 }
10308
10309 /* Call classed register method.
10310 * Note that zero falls through, no attribute, no error. */
10311 switch (PyObject_GetOptionalAttr(py_class, bpy_intern_str_register, &py_cls_meth)) {
10312 case 1: {
10313 PyObject *ret = PyObject_CallObject(py_cls_meth, nullptr);
10314 Py_DECREF(py_cls_meth);
10315 if (ret) {
10316 Py_DECREF(ret);
10317 }
10318 else {
10319 return nullptr;
10320 }
10321 break;
10322 }
10323 case -1: {
10324 return nullptr;
10325 }
10326 }
10327
10328 Py_RETURN_NONE;
10329}
10330
10332 StructRNA *srna,
10333 const char **r_prop_identifier)
10334{
10335 PropertyRNA *prop;
10336
10337 /* Verify properties. */
10338 const ListBase *lb = RNA_struct_type_properties(srna);
10339
10340 LISTBASE_FOREACH (LinkData *, link, lb) {
10341 prop = (PropertyRNA *)link;
10342 if (RNA_property_type(prop) == PROP_POINTER && !RNA_property_builtin(prop)) {
10343 PointerRNA tptr = RNA_pointer_create_discrete(nullptr, &RNA_Struct, srna_props);
10344
10345 if (RNA_property_pointer_type(&tptr, prop) == srna) {
10346 *r_prop_identifier = RNA_property_identifier(prop);
10347 return 1;
10348 }
10349 }
10350 }
10351
10352 return 0;
10353}
10354
10356
10357/* -------------------------------------------------------------------- */
10360
10362 /* Wrap. */
10363 pyrna_unregister_class_doc,
10364 ".. function:: unregister_class(cls)\n"
10365 "\n"
10366 " Unload the Python class from blender.\n"
10367 "\n"
10368 " :arg cls: Blender type class, \n"
10369 " see :mod:`bpy.utils.register_class` for classes which can \n"
10370 " be registered.\n"
10371 " :type cls: " BPY_TYPEDEF_REGISTERABLE_DOC
10372 "\n"
10373 "\n"
10374 " .. note::\n"
10375 "\n"
10376 " If the class has an *unregister* class method it will be called\n"
10377 " before unregistering.\n");
10379 "unregister_class",
10381 METH_O,
10382 pyrna_unregister_class_doc,
10383};
10384static PyObject *pyrna_unregister_class(PyObject * /*self*/, PyObject *py_class)
10385{
10386 bContext *C = nullptr;
10388 StructRNA *srna;
10389 PyObject *py_cls_meth;
10390 const char *error_prefix = "unregister_class(...):";
10391
10392 if (!PyType_Check(py_class)) {
10393 PyErr_Format(PyExc_ValueError,
10394 "%s expected a class argument, not '%.200s'",
10395 error_prefix,
10396 Py_TYPE(py_class)->tp_name);
10397 return nullptr;
10398 }
10399
10400#if 0
10401 if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == nullptr) {
10402 PyErr_Format(PyExc_ValueError, "%s not a registered as a subclass", error_prefix);
10403 return nullptr;
10404 }
10405#endif
10406
10407 if (!pyrna_write_check()) {
10408 PyErr_Format(PyExc_RuntimeError,
10409 "%s cannot run in readonly state '%.200s'",
10410 error_prefix,
10411 ((PyTypeObject *)py_class)->tp_name);
10412 return nullptr;
10413 }
10414
10415 srna = pyrna_struct_as_srna(py_class, false, error_prefix);
10416 if (srna == nullptr) {
10417 return nullptr;
10418 }
10419
10420 if ((srna->flag & STRUCT_RUNTIME) == 0) {
10421 PyErr_Format(PyExc_RuntimeError,
10422 "%s can't unregister a built-in class '%.200s'",
10423 error_prefix,
10424 ((PyTypeObject *)py_class)->tp_name);
10425 return nullptr;
10426 }
10427
10428 /* Check that we have a unregister callback for this type. */
10429 unreg = RNA_struct_unregister(srna);
10430
10431 if (!unreg) {
10432 PyErr_Format(PyExc_ValueError,
10433 "%s expected type '%.200s' subclassed from a registerable RNA type "
10434 "(unregister not supported)",
10435 error_prefix,
10436 ((PyTypeObject *)py_class)->tp_name);
10437 return nullptr;
10438 }
10439
10440 /* Call classed unregister method.
10441 * Note that zero falls through, no attribute, no error. */
10442 switch (PyObject_GetOptionalAttr(py_class, bpy_intern_str_unregister, &py_cls_meth)) {
10443 case 1: {
10444 PyObject *ret = PyObject_CallObject(py_cls_meth, nullptr);
10445 Py_DECREF(py_cls_meth);
10446 if (ret) {
10447 Py_DECREF(ret);
10448 }
10449 else {
10450 return nullptr;
10451 }
10452 break;
10453 }
10454 case -1: {
10455 return nullptr;
10456 }
10457 }
10458
10459 /* Should happen all the time, however it's very slow. */
10460 if (G.debug & G_DEBUG_PYTHON) {
10461 /* Remove all properties using this class. */
10462 StructRNA *srna_iter;
10463 PropertyRNA *prop_rna;
10464 const char *prop_identifier = nullptr;
10465
10467 prop_rna = RNA_struct_find_property(&ptr_rna, "structs");
10468
10469 /* Loop over all structs. */
10470 RNA_PROP_BEGIN (&ptr_rna, itemptr, prop_rna) {
10471 srna_iter = static_cast<StructRNA *>(itemptr.data);
10472 if (pyrna_srna_contains_pointer_prop_srna(srna_iter, srna, &prop_identifier)) {
10473 break;
10474 }
10475 }
10477
10478 if (prop_identifier) {
10479 PyErr_Format(PyExc_RuntimeError,
10480 "%s cannot unregister %s because %s.%s pointer property is using this",
10481 error_prefix,
10483 RNA_struct_identifier(srna_iter),
10484 prop_identifier);
10485 return nullptr;
10486 }
10487 }
10488
10489 /* Get the context, so register callback can do necessary refreshes. */
10490 C = BPY_context_get();
10491
10492 /* Call unregister. */
10493 unreg(CTX_data_main(C), srna); /* Calls bpy_class_free, this decref's py_class. */
10494
10495 /* Typically `bpy_class_free` will have removed, remove here just in case. */
10496 if (UNLIKELY(PyDict_Contains(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna))) {
10497 if (PyDict_DelItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == -1) {
10498 PyErr_Clear();
10499 }
10500 }
10501
10502 Py_RETURN_NONE;
10503}
10504
10506
10507/* -------------------------------------------------------------------- */
10510
10511void pyrna_struct_type_extend_capi(StructRNA *srna, PyMethodDef *method, PyGetSetDef *getset)
10512{
10513 /* See 'add_methods' in Python's 'typeobject.c'. */
10514 PyTypeObject *type = (PyTypeObject *)pyrna_srna_Subtype(srna);
10515 PyObject *dict = type->tp_dict;
10516 if (method != nullptr) {
10517 for (; method->ml_name != nullptr; method++) {
10518 PyObject *py_method;
10519
10520 if (method->ml_flags & METH_CLASS) {
10521 PyObject *cfunc = PyCFunction_New(method, (PyObject *)type);
10522 py_method = PyClassMethod_New(cfunc);
10523 Py_DECREF(cfunc);
10524 }
10525 else if (method->ml_flags & METH_STATIC) {
10526 py_method = PyCFunction_New(method, nullptr);
10527 }
10528 else {
10529 py_method = PyDescr_NewMethod(type, method);
10530 }
10531
10532 const int err = PyDict_SetItemString(dict, method->ml_name, py_method);
10533 Py_DECREF(py_method);
10534 BLI_assert(!(err < 0));
10535 UNUSED_VARS_NDEBUG(err);
10536 }
10537 }
10538
10539 if (getset != nullptr) {
10540 for (; getset->name != nullptr; getset++) {
10541 PyObject *descr = PyDescr_NewGetSet(type, getset);
10542 /* Ensure we're not overwriting anything that already exists. */
10543 BLI_assert(PyDict_GetItem(dict, PyDescr_NAME(descr)) == nullptr);
10544 PyDict_SetItem(dict, PyDescr_NAME(descr), descr);
10545 Py_DECREF(descr);
10546 }
10547 }
10548 Py_DECREF(type);
10549}
10550
10552
10553/* -------------------------------------------------------------------- */
10556
10557/* Access to the 'owner_id' so work-spaces can filter by add-on. */
10558
10559static PyObject *pyrna_bl_owner_id_get(PyObject * /*self*/)
10560{
10561 const char *name = RNA_struct_state_owner_get();
10562 if (name) {
10563 return PyUnicode_FromString(name);
10564 }
10565 Py_RETURN_NONE;
10566}
10567
10568static PyObject *pyrna_bl_owner_id_set(PyObject * /*self*/, PyObject *value)
10569{
10570 const char *name;
10571 if (value == Py_None) {
10572 name = nullptr;
10573 }
10574 else if (PyUnicode_Check(value)) {
10575 name = PyUnicode_AsUTF8(value);
10576 }
10577 else {
10578 PyErr_Format(PyExc_ValueError,
10579 "owner_set(...): "
10580 "expected None or a string, not '%.200s'",
10581 Py_TYPE(value)->tp_name);
10582 return nullptr;
10583 }
10585 Py_RETURN_NONE;
10586}
10587
10588#ifdef __GNUC__
10589# ifdef __clang__
10590# pragma clang diagnostic push
10591# pragma clang diagnostic ignored "-Wcast-function-type"
10592# else
10593# pragma GCC diagnostic push
10594# pragma GCC diagnostic ignored "-Wcast-function-type"
10595# endif
10596#endif
10597
10599 "_bl_owner_id_get",
10600 (PyCFunction)pyrna_bl_owner_id_get,
10601 METH_NOARGS,
10602 nullptr,
10603};
10605 "_bl_owner_id_set",
10606 (PyCFunction)pyrna_bl_owner_id_set,
10607 METH_O,
10608 nullptr,
10609};
10610
10611#ifdef __GNUC__
10612# ifdef __clang__
10613# pragma clang diagnostic pop
10614# else
10615# pragma GCC diagnostic pop
10616# endif
10617#endif
10618
ReportList * CTX_wm_reports(const bContext *C)
int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, blender::Vector< PointerRNA > *r_lb, PropertyRNA **r_prop, int *r_index, blender::StringRef *r_str, std::optional< int64_t > *r_int_value, ContextDataType *r_type)
ListBase CTX_data_dir_get(const bContext *C)
eContextResult
@ CTX_RESULT_MEMBER_NOT_FOUND
@ CTX_RESULT_OK
@ CTX_RESULT_NO_DATA
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
ContextDataType
@ G_DEBUG_PYTHON
#define G_MAIN
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:747
void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:741
bool IDP_ui_data_supported(const IDProperty *prop)
Definition idprop.cc:1713
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1251
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:164
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition idtype.cc:171
@ RPT_PRINT_HANDLED_BY_OWNER
Definition BKE_report.hh:60
@ RPT_STORE
Definition BKE_report.hh:56
@ RPT_DEBUG
Definition BKE_report.hh:34
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_reports_free(ReportList *reports)
Definition report.cc:97
void BKE_report_print_level_set(ReportList *reports, eReportType level)
Definition report.cc:265
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:82
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define ATTR_FALLTHROUGH
A dynamically sized string ADT.
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_dynstr.cc:37
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:295
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition BLI_ghash.cc:911
#define GHASH_ITER(gh_iter_, ghash_)
Definition BLI_ghash.h:318
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:702
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:787
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
Definition BLI_ghash.cc:895
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:307
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
@ EULER_ORDER_XYZ
@ EULER_ORDER_ZYX
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define STR_ELEM(...)
Definition BLI_string.h:661
void BLI_str_tolower_ascii(char *str, size_t len) ATTR_NONNULL(1)
Definition string.cc:956
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t size_t size_t BLI_snprintf_utf8(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define SNPRINTF_UTF8(dst, format,...)
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
unsigned char uchar
unsigned int uint
#define CLAMP(a, b, c)
#define ARRAY_SIZE(arr)
#define STREQLEN(a, b, n)
#define STRINGIFY(x)
#define UNUSED_VARS_NDEBUG(...)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define LIKELY(x)
struct CLG_LogRef * BPY_LOG_RNA
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
bool CLG_quiet_get()
Definition clog.cc:945
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
#define CLOG_TRACE(clg_ref,...)
Definition CLG_log.h:192
T * DEG_get_original(T *id)
@ ID_TAG_TEMP_MAIN
Definition DNA_ID.h:971
@ ID_FLAG_EMBEDDED_DATA
Definition DNA_ID.h:774
@ ID_WM
@ ID_WS
@ ID_SCR
Read Guarded memory(de)allocation.
#define RNA_PROP_END
#define RNA_STRUCT_BEGIN(sptr, prop)
#define RNA_STRUCT_END
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
int RNA_def_property_free_identifier(StructOrFunctionRNA *cont_, const char *identifier)
@ PARM_PYFUNC_REGISTER_OPTIONAL
Definition RNA_types.hh:557
@ PARM_RNAPTR
Definition RNA_types.hh:547
@ PARM_REQUIRED
Definition RNA_types.hh:545
@ PARM_OUTPUT
Definition RNA_types.hh:546
@ FUNC_USE_SELF_TYPE
Definition RNA_types.hh:909
@ FUNC_NO_SELF
Definition RNA_types.hh:907
@ FUNC_REGISTER
Definition RNA_types.hh:921
@ FUNC_REGISTER_OPTIONAL
Definition RNA_types.hh:923
@ FUNC_ALLOW_WRITE
Definition RNA_types.hh:929
@ STRUCT_RUNTIME
Definition RNA_types.hh:964
#define RNA_ENUM_BITFLAG_SIZE
Definition RNA_types.hh:222
StructRNA *(*)(Main *bmain, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) StructRegisterFunc
Definition RNA_types.hh:991
PropertyType
Definition RNA_types.hh:161
@ PROP_FLOAT
Definition RNA_types.hh:164
@ PROP_BOOLEAN
Definition RNA_types.hh:162
@ PROP_ENUM
Definition RNA_types.hh:166
@ PROP_INT
Definition RNA_types.hh:163
@ PROP_STRING
Definition RNA_types.hh:165
@ PROP_POINTER
Definition RNA_types.hh:167
@ PROP_COLLECTION
Definition RNA_types.hh:168
bool(*)(Main *bmain, StructRNA *type) StructUnregisterFunc
Definition RNA_types.hh:999
RawPropertyType
Definition RNA_types.hh:622
@ PROP_RAW_INT8
Definition RNA_types.hh:634
@ PROP_RAW_UINT64
Definition RNA_types.hh:633
@ PROP_RAW_INT
Definition RNA_types.hh:624
@ PROP_RAW_INT64
Definition RNA_types.hh:632
@ PROP_RAW_UNSET
Definition RNA_types.hh:623
@ PROP_RAW_BOOLEAN
Definition RNA_types.hh:627
@ PROP_RAW_CHAR
Definition RNA_types.hh:626
@ PROP_RAW_FLOAT
Definition RNA_types.hh:629
@ PROP_RAW_DOUBLE
Definition RNA_types.hh:628
@ PROP_RAW_UINT8
Definition RNA_types.hh:630
@ PROP_RAW_UINT16
Definition RNA_types.hh:631
@ PROP_RAW_SHORT
Definition RNA_types.hh:625
@ PROP_THICK_WRAP
Definition RNA_types.hh:423
@ PROP_DYNAMIC
Definition RNA_types.hh:428
@ PROP_PATH_SUPPORTS_BLEND_RELATIVE
Definition RNA_types.hh:456
@ PROP_ENUM_FLAG
Definition RNA_types.hh:404
@ PROP_REGISTER_OPTIONAL
Definition RNA_types.hh:412
@ PROP_NEVER_NULL
Definition RNA_types.hh:377
@ PROP_REGISTER
Definition RNA_types.hh:411
@ PROP_ID_SELF_CHECK
Definition RNA_types.hh:370
@ PROP_HIDDEN
Definition RNA_types.hh:338
@ PROP_IDPROPERTY
Definition RNA_types.hh:426
PropertySubType
Definition RNA_types.hh:232
@ PROP_MATRIX
Definition RNA_types.hh:265
@ PROP_BYTESTRING
Definition RNA_types.hh:240
@ PROP_FILENAME
Definition RNA_types.hh:238
@ PROP_COLOR
Definition RNA_types.hh:260
@ PROP_EULER
Definition RNA_types.hh:266
@ PROP_DIRPATH
Definition RNA_types.hh:237
@ PROP_COLOR_GAMMA
Definition RNA_types.hh:272
@ PROP_UNSIGNED
Definition RNA_types.hh:249
@ PROP_QUATERNION
Definition RNA_types.hh:267
@ PROP_FILEPATH
Definition RNA_types.hh:236
#define C
Definition RandGen.cpp:29
BMesh const char void * data
return true
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BPy_reports_write_stdout(const ReportList *reports, const char *header)
short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
bool BPy_errors_to_report(ReportList *reports)
void bpy_context_clear(struct bContext *C, const PyGILState_STATE *gilstate)
void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate)
struct bContext * BPY_context_get()
PyObject * self
PyObject * bpy_intern_str_bpy_types
PyObject * bpy_intern_str___name__
PyObject * bpy_intern_str_register
PyObject * bpy_intern_str_bl_rna
PyObject * bpy_intern_str___module__
PyObject * bpy_intern_str___doc__
PyObject * bpy_intern_str_attr
PyObject * bpy_intern_str___annotations__
PyObject * bpy_intern_str_unregister
PyObject * bpy_intern_str___slots__
PyObject * bpy_intern_str_properties
PyObject * BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
PyObject * BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
#define BPy_PropDeferred_CheckTypeExact(v)
Definition bpy_props.hh:37
#define PYRNA_STACK_ARRAY
Definition bpy_props.hh:39
static PyModuleDef bpy_types_module_def
Definition bpy_rna.cc:8856
static PyTypeObject pyrna_prop_collection_iter_Type
Definition bpy_rna.cc:7818
static PyObject * pyrna_struct_is_property_overridable_library(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:3878
const PointerRNA * pyrna_struct_as_ptr(PyObject *py_obj, const StructRNA *srna)
Definition bpy_rna.cc:9012
static PyObject * pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop)
Definition bpy_rna.cc:2647
static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype)
Definition bpy_rna.cc:544
static PyObject * pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args)
Definition bpy_rna.cc:5550
PyDoc_STRVAR(pyrna_struct_keys_doc, ".. method:: keys()\n" "\n" " Returns the keys of this objects custom properties (matches Python's\n" " dictionary function of the same name).\n" "\n" " :return: custom property keys.\n" " :rtype: :class:`idprop.types.IDPropertyGroupViewKeys`\n" "\n" BPY_DOC_ID_PROP_TYPE_NOTE)
static int pyrna_property_init(PyObject *self, PyObject *args, PyObject *)
Definition bpy_rna.cc:7676
PyTypeObject pyrna_struct_meta_idprop_Type
Definition bpy_rna.cc:7080
PyTypeObject pyrna_prop_Type
Definition bpy_rna.cc:7411
static PyObject * pyrna_register_class(PyObject *self, PyObject *py_class)
Definition bpy_rna.cc:10149
static PyObject * pyrna_bl_owner_id_get(PyObject *)
Definition bpy_rna.cc:10559
void pyrna_invalidate(BPy_DummyPointerRNA *self)
Definition bpy_rna.cc:178
static PyObject * pyrna_struct_dir(BPy_StructRNA *self)
Definition bpy_rna.cc:4503
StructRNA * pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix)
Definition bpy_rna.cc:8959
static PyTypeObject * bpy_class_check_any_bases_registered(PyTypeObject *cls)
Definition bpy_rna.cc:9986
static int pyrna_struct_compare(BPy_StructRNA *a, BPy_StructRNA *b)
Definition bpy_rna.cc:915
static PyObject * pyrna_prop_array_repr(BPy_PropertyArrayRNA *self)
Definition bpy_rna.cc:1204
static int pyrna_prop_array_contains(BPy_PropertyRNA *self, PyObject *value)
Definition bpy_rna.cc:3461
static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, PyObject *value)
Definition bpy_rna.cc:2195
static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self)
Definition bpy_rna.cc:2268
static PointerRNA * rna_module_ptr
Definition bpy_rna.cc:8702
static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, PyObject *key, PyObject *value)
Definition bpy_rna.cc:3331
static PyObject * pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject *key)
Definition bpy_rna.cc:2985
static PyObject * pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject *key)
Definition bpy_rna.cc:2782
static PyObject * pyrna_struct_type_recast(BPy_StructRNA *self)
Definition bpy_rna.cc:4276
PyMethodDef meth_bpy_owner_id_set
Definition bpy_rna.cc:10604
bool pyrna_id_CheckPyObject(PyObject *obj)
Definition bpy_rna.cc:8622
static int pyrna_deferred_register_class_recursive(StructRNA *srna, PyTypeObject *py_class)
Definition bpy_rna.cc:9247
static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self)
Definition bpy_rna.cc:2279
static void bpy_class_free_ex(PyObject *self, bool decref)
Definition bpy_rna.cc:9929
static PyObject * pyrna_srna_Subtype(StructRNA *srna)
Definition bpy_rna.cc:8296
static PyObject * pyrna_prop_array_foreach_set(BPy_PropertyArrayRNA *self, PyObject *args)
Definition bpy_rna.cc:6247
static PyObject * pyrna_struct_get_id_data(BPy_DummyPointerRNA *self, void *)
Definition bpy_rna.cc:5272
static PyObject * pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:4141
PyObject * BPY_rna_module()
Definition bpy_rna.cc:8703
static int pyrna_prop_compare(BPy_PropertyRNA *a, BPy_PropertyRNA *b)
Definition bpy_rna.cc:920
#define MATHUTILS_CB_SUBTYPE_COLOR
Definition bpy_rna.cc:511
static int prop_subscript_ass_array_slice__int_recursive(PyObject **value_items, int *value, int totdim, const int dimsize[], const int range[2])
Definition bpy_rna.cc:3095
static PyObject * pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:3777
static bool rna_disallow_writes
Definition bpy_rna.cc:418
#define PROP_ALL_VECTOR_SUBTYPES
Definition bpy_rna.cc:739
static PyObject * pyrna_struct_id_properties_ensure(BPy_StructRNA *self)
Definition bpy_rna.cc:4550
static PyObject * pyrna_struct_get_ancestors(BPy_StructRNA *self)
Definition bpy_rna.cc:4403
static const char * pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
Definition bpy_rna.cc:1278
static PyObject * pyrna_srna_PyBase(StructRNA *srna)
Definition bpy_rna.cc:8209
static long pyrna_prop_hash(BPy_PropertyRNA *self)
Definition bpy_rna.cc:1223
static PyObject * pyrna_struct_get_data(BPy_DummyPointerRNA *self, void *)
Definition bpy_rna.cc:5287
static void pyrna_prop_collection_iter_dealloc(PyObject *self)
Definition bpy_rna.cc:7949
static PyMethodDef pyrna_struct_methods[]
Definition bpy_rna.cc:6311
static PyObject * pyrna_struct_as_pointer(BPy_StructRNA *self)
Definition bpy_rna.cc:5532
void BPY_id_release(ID *id)
Definition bpy_rna.cc:397
static PyMethodDef pyrna_prop_collection_idprop_methods[]
Definition bpy_rna.cc:6478
static PyObject * pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject *pyname)
Definition bpy_rna.cc:5037
static PyObject * pyrna_func_CreatePyObject(const PointerRNA *ptr, FunctionRNA *func)
Definition bpy_rna.cc:8104
PyObject * pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
Definition bpy_rna.cc:748
static PyObject * pyrna_prop_array_to_py_index(BPy_PropertyArrayRNA *self, int index)
Definition bpy_rna.cc:2189
void BPY_free_srna_pytype(StructRNA *srna)
Definition bpy_rna.cc:10084
static PyObject * pyrna_struct_id_properties_clear(BPy_StructRNA *self)
Definition bpy_rna.cc:4628
static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum, PyObject *value)
Definition bpy_rna.cc:2417
static PyObject * pyrna_struct_items(BPy_StructRNA *self)
Definition bpy_rna.cc:3677
static PyObject * pyrna_bl_owner_id_set(PyObject *, PyObject *value)
Definition bpy_rna.cc:10568
void pyrna_struct_type_extend_capi(StructRNA *srna, PyMethodDef *method, PyGetSetDef *getset)
Definition bpy_rna.cc:10511
static PyObject * pyrna_struct_richcmp(PyObject *a, PyObject *b, int op)
Definition bpy_rna.cc:928
static PyMappingMethods pyrna_struct_as_mapping
Definition bpy_rna.cc:3635
static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item)
Definition bpy_rna.cc:9081
static PyObject * pyrna_prop_dir(BPy_PropertyRNA *self)
Definition bpy_rna.cc:5010
static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict)
Definition bpy_rna.cc:4421
static PyTypeObject pyrna_prop_collection_idprop_Type
Definition bpy_rna.cc:7580
static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key)
Definition bpy_rna.cc:3466
static PyObject * pyrna_struct_property_overridable_library_set(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:3913
#define BPY_DOC_ID_PROP_TYPE_NOTE
Definition bpy_rna.cc:138
static PyObject * pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length)
Definition bpy_rna.cc:2686
static PyMappingMethods pyrna_prop_array_as_mapping
Definition bpy_rna.cc:3397
static void pyrna_dir_members_py(PyObject *list, PyObject *self)
Definition bpy_rna.cc:4430
PyMethodDef meth_bpy_owner_id_get
Definition bpy_rna.cc:10598
static PyObject * pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, const char *keyname)
Definition bpy_rna.cc:2471
static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject *key, PyObject *value)
Definition bpy_rna.cc:2900
static int pyrna_prop_collection_iter_init(PyObject *self, PyObject *, PyObject *)
Definition bpy_rna.cc:7904
static PyObject * pyrna_prop_collection_foreach_get(BPy_PropertyRNA *self, PyObject *args)
Definition bpy_rna.cc:6053
static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, const char *error_prefix)
Definition bpy_rna.cc:1299
static PyObject * pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
Definition bpy_rna.cc:959
static PyObject * pyrna_prop_as_bytes(BPy_PropertyRNA *self)
Definition bpy_rna.cc:4223
static PyObject * pyrna_struct_id_properties_ui(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:4583
static int pyrna_prop_collection_string_subscript_supported_or_error(BPy_PropertyRNA *self, const char *error_prefix)
Definition bpy_rna.cc:2345
static PyObject * pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
Definition bpy_rna.cc:1370
static int bpy_class_validate_recursive(PointerRNA *dummy_ptr, StructRNA *srna, void *py_data, bool *have_function)
Definition bpy_rna.cc:9338
static void pyrna_property_dealloc(PyObject *self)
Definition bpy_rna.cc:7726
static PyObject * pyrna_prop_collection_foreach_set(BPy_PropertyRNA *self, PyObject *args)
Definition bpy_rna.cc:6066
static PyObject * pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, Py_ssize_t keynum)
Definition bpy_rna.cc:2451
bool pyrna_write_check()
Definition bpy_rna.cc:457
static PyObject * pyrna_prop_update(BPy_PropertyRNA *self)
Definition bpy_rna.cc:4260
static PyObject * pyrna_prop_path_from_id(BPy_PropertyRNA *self)
Definition bpy_rna.cc:4196
void pyrna_struct_validity_exception_only(const BPy_StructRNA *pysrna)
Definition bpy_rna.cc:151
static PyObject * pyrna_prop_path_from_module(BPy_PropertyRNA *self)
Definition bpy_rna.cc:4099
static PyNumberMethods pyrna_prop_collection_as_number
Definition bpy_rna.cc:3422
static PyObject * pyrna_struct_get_rna_type(BPy_PropertyRNA *self, void *)
Definition bpy_rna.cc:5296
static const char * BPy_PropertyPointerRNA_capsule_identifier
Definition bpy_rna.cc:114
static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int start, int stop, int length, PyObject *value_orig)
Definition bpy_rna.cc:3160
static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
Definition bpy_rna.cc:9223
void BPY_rna_init()
Definition bpy_rna.cc:8627
static PyObject * pyrna_prop_collection_values(BPy_PropertyRNA *self)
Definition bpy_rna.cc:5409
static PyObject * pyrna_srna_ExternalType(StructRNA *srna)
Definition bpy_rna.cc:8247
void BPY_rna_types_finalize_external_types(PyObject *submodule)
Definition bpy_rna.cc:8898
static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *value)
Definition bpy_rna.cc:2857
static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyObject *value)
Definition bpy_rna.cc:4878
int pyrna_struct_as_ptr_or_null_parse(PyObject *o, void *p)
Definition bpy_rna.cc:9045
int pyrna_struct_as_ptr_parse(PyObject *o, void *p)
Definition bpy_rna.cc:9034
static PyObject * pyrna_unregister_class(PyObject *self, PyObject *py_class)
Definition bpy_rna.cc:10384
static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject *value)
Definition bpy_rna.cc:4942
static uchar mathutils_rna_array_cb_index
Definition bpy_rna.cc:505
static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
Definition bpy_rna.cc:9577
static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int, int index)
Definition bpy_rna.cc:599
static PyObject * pyrna_property_new(PyTypeObject *type, PyObject *args, PyObject *)
Definition bpy_rna.cc:7636
StructRNA * srna_from_self(PyObject *self, const char *error_prefix)
Definition bpy_rna.cc:9058
static PySequenceMethods pyrna_struct_as_sequence
Definition bpy_rna.cc:3551
static PyObject * pyrna_func_doc_get(BPy_FunctionRNA *self, void *closure)
Definition bpy_rna.cc:7065
static int pyrna_prop_array_bool(BPy_PropertyRNA *self)
Definition bpy_rna.cc:2288
#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err)
Definition bpy_rna.cc:2305
PyObject * pyrna_id_CreatePyObject(ID *id)
Definition bpy_rna.cc:8601
static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
Definition bpy_rna.cc:8148
int pyrna_struct_validity_check(const BPy_StructRNA *pysrna)
Definition bpy_rna.cc:157
static PyObject * pyrna_prop_collection_iter_next(PyObject *self)
Definition bpy_rna.cc:8006
static int pyrna_prop_collection_subscript_is_valid_or_error(const PyObject *value)
Definition bpy_rna.cc:2318
static PyObject * pyrna_prop_collection_iter(PyObject *self)
Definition bpy_rna.cc:7999
static PyObject * pyrna_prop_array_foreach_get(BPy_PropertyArrayRNA *self, PyObject *args)
Definition bpy_rna.cc:6234
int pyrna_prop_validity_check(const BPy_PropertyRNA *self)
Definition bpy_rna.cc:166
static int mathutils_rna_generic_check(BaseMathObject *bmo)
Definition bpy_rna.cc:513
static PyObject * pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:3951
int pyrna_struct_validity_check_only(const BPy_StructRNA *pysrna)
Definition bpy_rna.cc:143
static PyObject * pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:3812
static PyObject * pyrna_struct_is_property_readonly(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:3845
static PyObject * pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, PyObject *key, const char *err_prefix, const bool err_not_found)
Definition bpy_rna.cc:2631
const PointerRNA * pyrna_struct_as_ptr_or_null(PyObject *py_obj, const StructRNA *srna)
Definition bpy_rna.cc:9026
static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr)
Definition bpy_rna.cc:4462
static PyObject * pyrna_prop_array_getattro(BPy_PropertyRNA *self, PyObject *pyname)
Definition bpy_rna.cc:5032
PyTypeObject pyrna_prop_array_Type
Definition bpy_rna.cc:7467
static void pyrna_func_error_prefix(BPy_FunctionRNA *self, PropertyRNA *parm, const int parm_index, char *error, const size_t error_size)
Definition bpy_rna.cc:6713
static int prop_subscript_ass_array_slice__bool_recursive(PyObject **value_items, bool *value, int totdim, const int dimsize[])
Definition bpy_rna.cc:3127
static PyNumberMethods pyrna_prop_array_as_number
Definition bpy_rna.cc:3410
static int prop_subscript_ass_array_int(BPy_PropertyArrayRNA *self, Py_ssize_t keynum, PyObject *value)
Definition bpy_rna.cc:3311
static PyObject * foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
Definition bpy_rna.cc:5832
static PySequenceMethods pyrna_prop_collection_as_sequence
Definition bpy_rna.cc:3536
static PyObject * pyrna_struct_get(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:5431
static Py_hash_t pyrna_struct_hash(BPy_StructRNA *self)
Definition bpy_rna.cc:1217
static PyObject * pyrna_struct_bl_rna_find_subclass_recursive(PyObject *cls, const char *id)
Definition bpy_rna.cc:4288
static PyGetSetDef pyrna_prop_getseters[]
Definition bpy_rna.cc:5306
PyTypeObject pyrna_struct_Type
Definition bpy_rna.cc:7172
static PyObject * pyrna_prop_collection_idprop_clear(BPy_PropertyRNA *self)
Definition bpy_rna.cc:5217
static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype)
Definition bpy_rna.cc:522
static PyObject * pyrna_struct_pop(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:5478
static PyObject * prop_subscript_ass_array_slice__as_seq_fast(PyObject *value, int length)
Definition bpy_rna.cc:3043
static void bpy_class_free(void *pyob_ptr)
Definition bpy_rna.cc:9974
static uchar mathutils_rna_matrix_cb_index
Definition bpy_rna.cc:656
static PySequenceMethods pyrna_prop_array_as_sequence
Definition bpy_rna.cc:3522
static PyObject * pyrna_struct_Subtype(PointerRNA *ptr)
Definition bpy_rna.cc:8414
static bool foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format)
Definition bpy_rna.cc:5779
static PyMethodDef pyrna_prop_methods[]
Definition bpy_rna.cc:6425
static int pyrna_srna_contains_pointer_prop_srna(StructRNA *srna_props, StructRNA *srna, const char **r_prop_identifier)
Definition bpy_rna.cc:10331
static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value)
Definition bpy_rna.cc:3497
PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
Definition bpy_rna.cc:1445
PyTypeObject pyrna_func_Type
Definition bpy_rna.cc:8048
static PyObject * pyrna_struct_str(BPy_StructRNA *self)
Definition bpy_rna.cc:991
static PyObject * kwnames_get_item_string(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, Py_ssize_t nkw, const char *parm_name)
Definition bpy_rna.cc:6688
int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class)
Definition bpy_rna.cc:9281
static PyGetSetDef pyrna_struct_getseters[]
Definition bpy_rna.cc:5321
int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const bool all_args, const char *error_prefix)
Definition bpy_rna.cc:1530
static void pyrna_struct_dealloc(PyObject *self)
Definition bpy_rna.cc:7339
static PyObject * pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
Definition bpy_rna.cc:4648
static PyMethodDef pyrna_prop_collection_methods[]
Definition bpy_rna.cc:6453
static int foreach_parse_args(BPy_PropertyRNA *self, PyObject *args, const char *function_name, const char **r_attr, PyObject **r_seq, int *r_tot, size_t *r_size, RawPropertyType *r_raw_type, int *r_attr_tot, bool *r_attr_signed)
Definition bpy_rna.cc:5672
void BPY_rna_types_dict_set(PyObject *dict)
Definition bpy_rna.cc:8237
static PyObject * pyrna_struct_CreatePyObject_from_type(const PointerRNA *ptr, PyTypeObject *tp, void **instance)
Definition bpy_rna.cc:8427
static Mathutils_Callback mathutils_rna_array_cb
Definition bpy_rna.cc:647
static void pyrna_prop_collection_string_subscript_unsupported_error(BPy_PropertyRNA *self, const char *error_prefix)
Definition bpy_rna.cc:2335
static PyObject * pyrna_struct_values(BPy_StructRNA *self)
Definition bpy_rna.cc:3702
void BPY_rna_exit()
Definition bpy_rna.cc:8680
static PyObject * pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
Definition bpy_rna.cc:6506
static int pyrna_prop_collection_bool(BPy_PropertyRNA *self)
Definition bpy_rna.cc:2295
static PyObject * pyrna_struct_bl_rna_get_subclass_py(PyObject *cls, PyObject *args)
Definition bpy_rna.cc:4331
PyObject * BPY_rna_types()
Definition bpy_rna.cc:8868
static bool foreach_attr_type(BPy_PropertyRNA *self, const char *attr, RawPropertyType *r_raw_type, int *r_attr_tot, bool *r_attr_signed, bool *r_is_empty)
Definition bpy_rna.cc:5637
PyMethodDef meth_bpy_unregister_class
Definition bpy_rna.cc:10378
static short pyrna_rotation_euler_order_get(PointerRNA *ptr, const short order_fallback, PropertyRNA **r_prop_eul_order)
Definition bpy_rna.cc:713
static PyObject * bpy_types_dict
Definition bpy_rna.cc:8236
static int prop_subscript_ass_array_slice__float_recursive(PyObject **value_items, float *value, int totdim, const int dimsize[], const float range[2])
Definition bpy_rna.cc:3063
static const char * BPy_capsule_PointerRNA_identifier
Definition bpy_rna.cc:102
static void pyrna_prop_warn_deprecated(const PointerRNA *ptr, const PropertyRNA *prop, const DeprecatedRNA *deprecated)
Definition bpy_rna.cc:183
PyObject * pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop)
Definition bpy_rna.cc:8553
static int pyrna_struct_init(PyObject *self, PyObject *args, PyObject *)
Definition bpy_rna.cc:7282
static void bpy_types_module_free(void *self)
Definition bpy_rna.cc:8839
void pyrna_write_set(bool val)
Definition bpy_rna.cc:464
static PyObject * pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, const int index)
Definition bpy_rna.cc:1153
static PyObject * pyrna_prop_collection_idprop_add(BPy_PropertyRNA *self)
Definition bpy_rna.cc:5158
PyMethodDef meth_bpy_register_class
Definition bpy_rna.cc:10147
static int bpy_class_validate(PointerRNA *dummy_ptr, void *py_data, bool *have_function)
Definition bpy_rna.cc:9571
static PyObject * pyrna_struct_repr(BPy_StructRNA *self)
Definition bpy_rna.cc:1027
#define MATHUTILS_CB_SUBTYPE_VEC
Definition bpy_rna.cc:509
static int pyrna_deferred_register_class_from_type_hints(StructRNA *srna, PyTypeObject *py_class)
Definition bpy_rna.cc:9167
void pyrna_alloc_types()
Definition bpy_rna.cc:10052
static PyObject * pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key_ob)
Definition bpy_rna.cc:5603
static int mathutils_rna_matrix_set(BaseMathObject *bmo, int)
Definition bpy_rna.cc:672
static PyObject * pyrna_prop_collection_keys(BPy_PropertyRNA *self)
Definition bpy_rna.cc:5347
static int pyrna_property_array_init(PyObject *self, PyObject *args, PyObject *)
Definition bpy_rna.cc:7747
#define MATHUTILS_CB_SUBTYPE_EUL
Definition bpy_rna.cc:508
static PyObject * pyrna_prop_repr(BPy_PropertyRNA *self)
Definition bpy_rna.cc:1199
static PyGetSetDef pyrna_func_getseters[]
Definition bpy_rna.cc:5332
void BPY_update_rna_module()
Definition bpy_rna.cc:8715
static PyTypeObject * bpy_class_check_any_subclasses_registered(PyTypeObject *cls)
Definition bpy_rna.cc:10016
static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pyname, PyObject *value)
Definition bpy_rna.cc:5114
static PyObject * pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args)
Definition bpy_rna.cc:4355
static int pyrna_prop_to_enum_bitfield(PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, const char *error_prefix)
Definition bpy_rna.cc:1326
static PyObject * pyrna_func_repr(BPy_FunctionRNA *self)
Definition bpy_rna.cc:1209
static PyMappingMethods pyrna_prop_collection_as_mapping
Definition bpy_rna.cc:3403
bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
Definition bpy_rna.cc:8611
static PyObject * pyrna_struct_get_nameprop_as_pyobject(PointerRNA *ptr, BPy_NamePropAsPyObject_Cache &nameprop_cache)
Definition bpy_rna.cc:365
#define BPY_TYPEDEF_REGISTERABLE_DOC
Definition bpy_rna.cc:10100
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
Definition bpy_rna.cc:8496
static PyMethodDef bpy_types_module_methods[]
Definition bpy_rna.cc:8825
static PyObject * bpy_types_module_getattro(PyObject *self, PyObject *pyname)
Definition bpy_rna.cc:8756
static PyObject * pyrna_prop_str(BPy_PropertyRNA *self)
Definition bpy_rna.cc:1084
static PyObject * pyrna_prop_collection_items(BPy_PropertyRNA *self)
Definition bpy_rna.cc:5372
static PyObject * pyprop_array_foreach_getset(BPy_PropertyArrayRNA *self, PyObject *args, const bool do_set)
Definition bpy_rna.cc:6073
static int mathutils_rna_matrix_get(BaseMathObject *bmo, int)
Definition bpy_rna.cc:658
static PyObject * bpy_types_module_dir(PyObject *self)
Definition bpy_rna.cc:8792
static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int, int index)
Definition bpy_rna.cc:613
static PyObject * pyrna_prop_collection_iter_new(PyTypeObject *type, PyObject *, PyObject *)
Definition bpy_rna.cc:7874
static PyObject * pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *)
Definition bpy_rna.cc:7237
static PyObject * pyrna_struct_keys(BPy_StructRNA *self)
Definition bpy_rna.cc:3652
static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self, PyObject *key, const char *err_prefix, const short err_not_found, PointerRNA *r_ptr)
Definition bpy_rna.cc:2542
static PyObject * pyrna_prop_array_iter(BPy_PropertyArrayRNA *self)
Definition bpy_rna.cc:6256
#define MATHUTILS_CB_SUBTYPE_QUAT
Definition bpy_rna.cc:510
static PyObject * pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum)
Definition bpy_rna.cc:2357
static PyObject * pyrna_prop_collection_idprop_move(BPy_PropertyRNA *self, PyObject *args)
Definition bpy_rna.cc:5241
static PyMethodDef pyrna_prop_array_methods[]
Definition bpy_rna.cc:6440
BPy_StructRNA * bpy_context_module
Definition bpy_rna.cc:96
PyObject * pyrna_struct_CreatePyObject_with_primitive_support(PointerRNA *ptr)
Definition bpy_rna.cc:8532
static void pyrna_func_dealloc(PyObject *self)
Definition bpy_rna.cc:8124
static PyObject * pyrna_prop_collection_idprop_remove(BPy_PropertyRNA *self, PyObject *value)
Definition bpy_rna.cc:5187
static PyObject * pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key)
Definition bpy_rna.cc:3565
static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObject *value)
Definition bpy_rna.cc:3600
static PyObject * pyrna_prop_collection_iter_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop)
Definition bpy_rna.cc:7974
static StructRNA * srna_from_ptr(PointerRNA *ptr)
Definition bpy_rna.cc:8402
static PyObject * pyrna_struct_path_from_module(BPy_StructRNA *self, PyObject *args)
Definition bpy_rna.cc:4017
static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
Definition bpy_rna.cc:420
static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix)
Definition bpy_rna.cc:1600
static int rna_function_register_arg_count(FunctionRNA *func, int *min_count)
Definition bpy_rna.cc:9301
PyTypeObject pyrna_prop_collection_Type
Definition bpy_rna.cc:7523
static PyObject * pyrna_func_vectorcall(PyObject *callable, PyObject *const *args, size_t nargsf, PyObject *kwnames)
Definition bpy_rna.cc:6745
static PyObject * pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args, PyObject *kw)
Definition bpy_rna.cc:3735
static Mathutils_Callback mathutils_rna_matrix_cb
Definition bpy_rna.cc:705
int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix)
PyObject * pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index)
#define PYRNA_STRUCT_IS_VALID(pysrna)
Definition bpy_rna.hh:110
int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value)
#define BPy_StructRNA_CheckExact(v)
Definition bpy_rna.hh:74
#define PYRNA_STRUCT_CHECK_OBJ(obj)
Definition bpy_rna.hh:78
int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix)
#define PYRNA_STRUCT_CHECK_INT(obj)
Definition bpy_rna.hh:83
#define PYRNA_STRUCT_CHECK_OBJ_UNLESS(obj, unless)
Definition bpy_rna.hh:100
#define PYRNA_PROP_CHECK_OBJ(obj)
Definition bpy_rna.hh:89
#define PYRNA_PROP_CHECK_INT(obj)
Definition bpy_rna.hh:94
#define BPy_PropertyRNA_CheckExact(v)
Definition bpy_rna.hh:76
#define BPy_StructRNA_Check(v)
Definition bpy_rna.hh:73
#define BPy_PropertyRNA_Check(v)
Definition bpy_rna.hh:75
PyObject * pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index)
PyObject * pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop)
char pyrna_struct_driver_add_doc[]
char pyrna_struct_keyframe_insert_doc[]
PyObject * pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw)
PyObject * pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
PyObject * pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
char pyrna_struct_driver_remove_doc[]
char pyrna_struct_keyframe_delete_doc[]
PyObject * pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw)
PyObject * pyrna_callback_classmethod_remove(PyObject *, PyObject *args)
PyObject * pyrna_callback_classmethod_add(PyObject *, PyObject *args)
long long int int64_t
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void append(const T &value)
constexpr bool is_empty() const
constexpr int64_t size() const
constexpr const char * data() const
constexpr const char * c_str() const
nullptr float
#define offsetof(t, d)
#define GS(x)
uint pos
uint col
#define printf(...)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
float length(VecOp< float, D >) RET
PyObject * BPy_Wrap_GetKeys_View_WithID(ID *id, IDProperty *prop)
int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val)
PyObject * BPy_Wrap_GetItems_View_WithID(ID *id, IDProperty *prop)
PyTypeObject BPy_IDGroup_Type
PyObject * BPy_IDGroup_MapDataToPy(IDProperty *prop)
PyObject * BPy_IDGroup_WrapData(ID *id, IDProperty *prop, IDProperty *parent)
PyObject * BPy_Wrap_GetValues_View_WithID(ID *id, IDProperty *prop)
PyTypeObject BPy_IDPropertyUIManager_Type
int count
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
uchar Mathutils_RegisterCallback(Mathutils_Callback *cb)
Definition mathutils.cc:521
int(*)(BaseMathObject *, int) BaseMathGetFunc
Definition mathutils.hh:105
int(*)(BaseMathObject *, int) BaseMathSetFunc
Definition mathutils.hh:107
int(*)(BaseMathObject *, int, int) BaseMathSetIndexFunc
Definition mathutils.hh:111
int(*)(BaseMathObject *) BaseMathCheckFunc
Definition mathutils.hh:103
int(*)(BaseMathObject *, int, int) BaseMathGetIndexFunc
Definition mathutils.hh:109
PyObject * Color_CreatePyObject(const float col[3], PyTypeObject *base_type)
PyObject * Color_CreatePyObject_cb(PyObject *cb_user, uchar cb_type, uchar cb_subtype)
PyObject * Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type)
PyObject * Euler_CreatePyObject_cb(PyObject *cb_user, const short order, uchar cb_type, uchar cb_subtype)
PyObject * Matrix_CreatePyObject_cb(PyObject *cb_user, const ushort col_num, const ushort row_num, uchar cb_type, uchar cb_subtype)
PyObject * Matrix_CreatePyObject(const float *mat, const ushort col_num, const ushort row_num, PyTypeObject *base_type)
PyObject * Quaternion_CreatePyObject_cb(PyObject *cb_user, uchar cb_type, uchar cb_subtype)
PyObject * Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type)
PyObject * Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
PyObject * Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype)
static ulong state[N]
#define G(x, y, z)
static void error(const char *str)
StringRefNull node_type_find_alias(StringRefNull alias)
Definition node.cc:2388
bNodeType * node_type_find(StringRef idname)
Definition node.cc:2379
int pyrna_enum_bitfield_from_set(const EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix)
char * pyrna_enum_repr(const EnumPropertyItem *item)
int16_t PyC_Long_AsI16(PyObject *value)
uint8_t PyC_Long_AsU8(PyObject *value)
PyObject * PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format,...)
void PyC_ObSpit(const char *name, PyObject *var)
int8_t PyC_Long_AsI8(PyObject *value)
PyObject * PyC_UnicodeFromBytesAndSize(const char *str, Py_ssize_t size)
PyObject * PyC_UnicodeFromBytes(const char *str)
uint64_t PyC_Long_AsU64(PyObject *value)
void PyC_ObSpitStr(char *result, size_t result_maxncpy, PyObject *var)
PyObject * PyC_ExceptionBuffer()
int PyC_Long_AsBool(PyObject *value)
void PyC_FileAndNum(const char **r_filename, int *r_lineno)
uint16_t PyC_Long_AsU16(PyObject *value)
PyObject * PyC_UnicodeFromStdStr(const std::string &str)
int PyC_ParseBool(PyObject *o, void *p)
const char * PyC_UnicodeAsBytes(PyObject *py_str, PyObject **r_coerce)
header-only compatibility defines.
#define PyObject_GetOptionalAttr
#define Py_HashPointer
Py_DECREF(oname)
#define PY_ARG_PARSER_HEAD_COMPAT()
const char * name
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_collection_lookup_int_has_fn(PropertyRNA *prop)
bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
StructRegisterFunc RNA_struct_register(StructRNA *type)
bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
const StructRNA * RNA_struct_base_child_of(const StructRNA *type, const StructRNA *parent_type)
bool RNA_property_update_check(PropertyRNA *prop)
bool RNA_property_array_check(PropertyRNA *prop)
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
const char * RNA_function_identifier(FunctionRNA *func)
void RNA_parameter_list_end(ParameterIterator *)
void RNA_struct_state_owner_set(const char *name)
void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
IDProperty ** RNA_struct_idprops_p(PointerRNA *ptr)
int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
bool RNA_struct_is_ID(const StructRNA *type)
const ListBase * RNA_struct_type_properties(StructRNA *srna)
void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
const ListBase * RNA_struct_type_functions(StructRNA *srna)
bool RNA_struct_idprops_check(const StructRNA *srna)
bool RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr)
bool RNA_property_collection_is_empty(PointerRNA *ptr, PropertyRNA *prop)
int RNA_function_defined(FunctionRNA *func)
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
char * RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_collection_skip(CollectionPropertyIterator *iter, int num)
bool RNA_property_collection_lookup_string_has_nameprop(PropertyRNA *prop)
int RNA_property_collection_raw_get(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname, void *array, RawPropertyType type, int len)
int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dimension)
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost)
bool RNA_property_collection_lookup_string_supported(PropertyRNA *prop)
void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
PropertyType RNA_property_type(PropertyRNA *prop)
const PointerRNA PointerRNA_NULL
char * RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
void ** RNA_struct_instance(PointerRNA *ptr)
void RNA_parameter_list_free(ParameterList *parms)
IDProperty * RNA_struct_idprops(PointerRNA *ptr, bool create)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
size_t RNA_raw_type_sizeof(RawPropertyType type)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_struct_identifier(const StructRNA *type)
bool RNA_struct_idprops_contains_datablock(const StructRNA *type)
void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
bool RNA_enum_id_from_value(const EnumPropertyItem *item, int value, const char **r_identifier)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_collection_next(CollectionPropertyIterator *iter)
char * RNA_struct_name_get_alloc_ex(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len, PropertyRNA **r_nameprop)
void RNA_parameter_list_next(ParameterIterator *iter)
const char * RNA_function_ui_description(FunctionRNA *func)
int RNA_property_array_dimension(const PointerRNA *ptr, PropertyRNA *prop, int length[])
PropertyRNA * RNA_struct_type_find_property_no_base(StructRNA *srna, const char *identifier)
int RNA_function_flag(FunctionRNA *func)
std::string RNA_function_as_string_keywords(bContext *C, FunctionRNA *func, const bool as_function, const bool all_args, const int max_prop_length)
PointerRNA RNA_pointer_create_from_ancestor(const PointerRNA &ptr, const int ancestor_idx)
const DeprecatedRNA * RNA_property_deprecated(const PropertyRNA *prop)
int RNA_property_flag(PropertyRNA *prop)
RawPropertyType RNA_property_raw_type(PropertyRNA *prop)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
bool RNA_property_builtin(PropertyRNA *prop)
bool RNA_struct_system_idprops_register_check(const StructRNA *type)
const char * RNA_struct_ui_description(const StructRNA *type)
int RNA_parameter_list_arg_count(const ParameterList *parms)
bool RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
void RNA_property_string_set_bytes(PointerRNA *ptr, PropertyRNA *prop, const char *value, int len)
bool RNA_struct_system_idprops_check(StructRNA *srna)
void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
StructRNA * RNA_struct_base(StructRNA *type)
FunctionRNA * RNA_struct_find_function(StructRNA *srna, const char *identifier)
bool RNA_property_is_idprop(const PropertyRNA *prop)
int RNA_property_string_maxlength(PropertyRNA *prop)
const char * RNA_struct_state_owner_get()
bool RNA_struct_idprops_datablock_allowed(const StructRNA *type)
bool RNA_property_editable(const PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_recast(PointerRNA *ptr)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
PropertyRNA * RNA_struct_name_property(const StructRNA *type)
void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
PointerRNA RNA_main_pointer_create(Main *main)
void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
int RNA_function_call(bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
bool RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
ParameterList * RNA_parameter_list_create(ParameterList *parms, PointerRNA *, FunctionRNA *func)
void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
void RNA_property_collection_end(CollectionPropertyIterator *iter)
bool RNA_property_collection_lookup_string_has_fn(PropertyRNA *prop)
PointerRNA RNA_blender_rna_pointer_create()
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
void RNA_parameter_list_begin(ParameterList *parms, ParameterIterator *iter)
PropertyRNA * RNA_struct_iterator_property(StructRNA *type)
void RNA_property_enum_items_ex(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const bool use_static, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
int RNA_parameter_flag(PropertyRNA *prop)
void * RNA_struct_py_type_get(StructRNA *srna)
bool RNA_property_editable_flag(const PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_collection_raw_set(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname, void *array, RawPropertyType type, int len)
const char * RNA_property_identifier(const PropertyRNA *prop)
const ListBase * RNA_function_defined_parameters(FunctionRNA *func)
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const bool *values)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
bool RNA_property_overridable_library_set(PointerRNA *, PropertyRNA *prop, const bool is_overridable)
bool RNA_property_overridable_get(const PointerRNA *ptr, PropertyRNA *prop)
StructRNA RNA_PropertyGroup
std::optional< std::string > RNA_path_from_ID_to_struct(const PointerRNA *ptr)
Definition rna_path.cc:1014
std::optional< std::string > RNA_path_from_real_ID_to_struct(Main *bmain, const PointerRNA *ptr, ID **r_real)
Definition rna_path.cc:1056
std::optional< std::string > RNA_path_from_real_ID_to_property_index(Main *bmain, const PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, ID **r_real_id)
Definition rna_path.cc:1178
std::optional< std::string > RNA_path_full_property_py_ex(const PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback)
Definition rna_path.cc:1283
bool RNA_path_resolve_full_maybe_null(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition rna_path.cc:554
std::optional< std::string > RNA_path_full_struct_py(const PointerRNA *ptr)
Definition rna_path.cc:1267
std::string RNA_path_full_ID_py(ID *id)
Definition rna_path.cc:1232
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition rna_path.cc:1173
std::string RNA_path_from_ptr_to_property_index(const PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index)
Definition rna_path.cc:1148
const EnumPropertyItem rna_enum_property_type_items[]
Definition rna_rna.cc:43
const EnumPropertyItem rna_enum_dummy_NULL_items[]
Definition rna_rna.cc:26
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
PyObject_HEAD std::optional< PointerRNA > ptr
Definition bpy_rna.hh:121
vectorcallfunc vectorcall
Definition bpy_rna.hh:197
PyObject_HEAD std::optional< PointerRNA > ptr
Definition bpy_rna.hh:191
FunctionRNA * func
Definition bpy_rna.hh:192
PyObject_VAR_HEAD IDProperty * property
PyObject_VAR_HEAD struct ID * owner_id
struct IDProperty * parent
struct IDProperty * prop
PyObject *(* nameprop_as_py_object_fn)(const char *, Py_ssize_t)
Definition bpy_rna.cc:358
PyObject_HEAD std::optional< PointerRNA > ptr
Definition bpy_rna.hh:163
PropertyRNA * prop
Definition bpy_rna.hh:164
PyObject_HEAD std::optional< CollectionPropertyIterator > iter
Definition bpy_rna.hh:182
PyObject_HEAD std::optional< PointerRNA > ptr
Definition bpy_rna.hh:150
PropertyRNA * prop
Definition bpy_rna.hh:151
StructRNA * type
Definition bpy_rna.hh:245
const PointerRNA * ptr
Definition bpy_rna.hh:247
PyObject_HEAD std::optional< PointerRNA > ptr
Definition bpy_rna.hh:130
PropertyRNA * prop
Definition bpy_rna.cc:8753
std::optional< PointerRNA > ptr
Definition bpy_rna.cc:8751
blender::Vector< PointerRNA > items
Definition RNA_types.hh:619
short removal_version
const char * note
unsigned char order
StructRNA * srna
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
short flag
Definition DNA_ID.h:438
ListBase libraries
Definition BKE_main.hh:279
PropertyRNA * parm
Definition RNA_types.hh:858
ID * owner_id
Definition RNA_types.hh:51
StructRNA * type
Definition RNA_types.hh:52
void * data
Definition RNA_types.hh:53
ListBase list
Definition BKE_report.hh:75
Defines a node type.
Definition BKE_node.hh:238
struct ReportList * reports
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len
static DynamicLibrary lib
PointerRNA * ptr
Definition wm_files.cc:4238
uint8_t flag
Definition wm_window.cc:145