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