diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-02-20 08:16:43 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-02-20 08:19:33 +0300 |
commit | 37e6a1995ac7eeabd5b6a56621ad5a850dae4149 (patch) | |
tree | 5a3531d6e7a033c7afe81f97ac3dc157c79cb00a /source/blender/python/intern/bpy_props.c | |
parent | 4cd808f912173b8c59c217860313e178102e893e (diff) |
PyAPI: use a new type for storing the deferred result of bpy.props
This is needed to support Python 3.10's Postponed annotation evaluation.
It also simplifies type checking.
Diffstat (limited to 'source/blender/python/intern/bpy_props.c')
-rw-r--r-- | source/blender/python/intern/bpy_props.c | 92 |
1 files changed, 70 insertions, 22 deletions
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 878bf4aec5d..c596f81a91c 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -193,6 +193,71 @@ static const EnumPropertyItem property_subtype_array_items[] = { "'XYZ', 'XYZ_LENGTH', 'COLOR_GAMMA', 'COORDINATES', 'LAYER', 'LAYER_MEMBER', 'NONE'].\n" \ " :type subtype: string\n" +/* -------------------------------------------------------------------- */ +/** \name Deferred Property Type + * + * Operators and classes use this so it can store the arguments given but defer + * running it until the operator runs where these values are used to setup + * the default arguments for that operator instance. + * \{ */ + +static void bpy_prop_deferred_dealloc(BPy_PropDeferred *self) +{ + if (self->kw) { + PyObject_GC_UnTrack(self); + Py_CLEAR(self->kw); + } + PyObject_GC_Del(self); +} + +static int bpy_prop_deferred_traverse(BPy_PropDeferred *self, visitproc visit, void *arg) +{ + Py_VISIT(self->kw); + return 0; +} + +static int bpy_prop_deferred_clear(BPy_PropDeferred *self) +{ + Py_CLEAR(self->kw); + return 0; +} + +static PyObject *bpy_prop_deferred_repr(BPy_PropDeferred *self) +{ + return PyUnicode_FromFormat("<%.200s, %R, %R>", Py_TYPE(self)->tp_name, self->fn, self->kw); +} + +PyTypeObject bpy_prop_deferred_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "bpy_prop_deferred", + .tp_basicsize = sizeof(BPy_PropDeferred), + .tp_dealloc = (destructor)bpy_prop_deferred_dealloc, + .tp_repr = (reprfunc)bpy_prop_deferred_repr, + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + + .tp_traverse = (traverseproc)bpy_prop_deferred_traverse, + .tp_clear = (inquiry)bpy_prop_deferred_clear, +}; + +static PyObject *bpy_prop_deferred_data_CreatePyObject(PyObject *fn, PyObject *kw) +{ + BPy_PropDeferred *self = PyObject_GC_New(BPy_PropDeferred, &bpy_prop_deferred_Type); + self->fn = fn; + if (kw == NULL) { + kw = PyDict_New(); + } + else { + Py_INCREF(kw); + } + self->kw = kw; + PyObject_GC_Track(self); + return (PyObject *)self; +} + +/** \} */ + /* PyObject's */ static PyObject *pymeth_BoolProperty = NULL; static PyObject *pymeth_BoolVectorProperty = NULL; @@ -248,27 +313,6 @@ static void bpy_prop_assign_flag_override(PropertyRNA *prop, const int flag_over RNA_def_property_override_flag(prop, flag_override); } -/* operators and classes use this so it can store the args given but defer - * running it until the operator runs where these values are used to setup - * the default args for that operator instance */ -static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) -{ - PyObject *ret = PyTuple_New(2); - PyTuple_SET_ITEM(ret, 0, func); - Py_INCREF(func); - - if (kw == NULL) { - kw = PyDict_New(); - } - else { - Py_INCREF(kw); - } - - PyTuple_SET_ITEM(ret, 1, kw); - - return ret; -} - /* callbacks */ static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, @@ -1997,7 +2041,7 @@ static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop, if (PyErr_Occurred()) { \ return NULL; \ } \ - return bpy_prop_deferred_return(pymeth_##_func, kw); \ + return bpy_prop_deferred_data_CreatePyObject(pymeth_##_func, kw); \ } \ (void)0 @@ -3668,5 +3712,9 @@ PyObject *BPY_rna_props(void) ASSIGN_STATIC(CollectionProperty); ASSIGN_STATIC(RemoveProperty); + if (PyType_Ready(&bpy_prop_deferred_Type) < 0) { + return NULL; + } + return submodule; } |