Merge branch 'master' into blender2.8
[blender.git] / source / blender / python / intern / bpy_rna.c
index b36a6e0665198f829068bc7470117967b3cc9bc1..77728829066fd5f1aa272e81a4aae52992ba94de 100644 (file)
@@ -315,7 +315,7 @@ static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
        ID *id = ptr->id.data;
        if (id) {
                const short idcode = GS(id->name);
-               if (!ELEM(idcode, ID_WM, ID_SCR)) { /* may need more added here */
+               if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */
                        const char *idtype = BKE_idcode_to_name(idcode);
                        const char *pyname;
                        if (key && PyUnicode_Check(key)) pyname = _PyUnicode_AsString(key);
@@ -1729,7 +1729,25 @@ static int pyrna_py_to_prop(
                                const int subtype = RNA_property_subtype(prop);
                                const char *param;
 
-                               if (subtype == PROP_BYTESTRING) {
+                               if (value == Py_None) {
+                                       if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) {
+                                               if (data) {
+                                                       *((char **)data) = (char *)NULL;
+                                               }
+                                               else {
+                                                       RNA_property_string_set(ptr, prop, NULL);
+                                               }
+                                       }
+                                       else {
+                                               PyC_Err_Format_Prefix(
+                                                       PyExc_TypeError,
+                                                       "%.200s %.200s.%.200s doesn't support None from string types",
+                                                       error_prefix, RNA_struct_identifier(ptr->type),
+                                                       RNA_property_identifier(prop));
+                                               return -1;
+                                       }
+                               }
+                               else if (subtype == PROP_BYTESTRING) {
 
                                        /* Byte String */
 
@@ -1849,19 +1867,28 @@ static int pyrna_py_to_prop(
                                 * class mixing if this causes problems in the future it should be removed.
                                 */
                                if ((ptr_type == &RNA_AnyType) &&
-                                   (BPy_StructRNA_Check(value)) &&
-                                   (RNA_struct_is_a(((BPy_StructRNA *)value)->ptr.type, &RNA_Operator)))
+                                   (BPy_StructRNA_Check(value)))
                                {
-                                       value = PyObject_GetAttrString(value, "properties");
-                                       value_new = value;
+                                       const StructRNA *base_type =
+                                               RNA_struct_base_child_of(((const BPy_StructRNA *)value)->ptr.type, NULL);
+                                       if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) {
+                                               value = PyObject_GetAttr(value, bpy_intern_str_properties);
+                                               value_new = value;
+                                       }
                                }
 
-
-                               /* if property is an OperatorProperties pointer and value is a map,
+                               /* if property is an OperatorProperties/GizmoProperties pointer and value is a map,
                                 * forward back to pyrna_pydict_to_props */
-                               if (RNA_struct_is_a(ptr_type, &RNA_OperatorProperties) && PyDict_Check(value)) {
-                                       PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
-                                       return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+                               if (PyDict_Check(value)) {
+                                       const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL);
+                                       if (base_type == &RNA_OperatorProperties) {
+                                               PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+                                               return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+                                       }
+                                       else if (base_type == &RNA_GizmoProperties) {
+                                               PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+                                               return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+                                       }
                                }
 
                                /* another exception, allow to pass a collection as an RNA property */
@@ -3500,6 +3527,68 @@ static PyObject *pyrna_struct_is_property_readonly(BPy_StructRNA *self, PyObject
        return PyBool_FromLong(!RNA_property_editable(&self->ptr, prop));
 }
 
+
+PyDoc_STRVAR(pyrna_struct_is_property_overridable_static_doc,
+".. method:: is_property_overridable_static(property)\n"
+"\n"
+"   Check if a property is statically overridable.\n"
+"\n"
+"   :return: True when the property is statically overridable.\n"
+"   :rtype: boolean\n"
+);
+static PyObject *pyrna_struct_is_property_overridable_static(BPy_StructRNA *self, PyObject *args)
+{
+       PropertyRNA *prop;
+       const char *name;
+
+       PYRNA_STRUCT_CHECK_OBJ(self);
+
+       if (!PyArg_ParseTuple(args, "s:is_property_overridable_static", &name)) {
+               return NULL;
+       }
+
+       if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
+               PyErr_Format(PyExc_TypeError,
+                            "%.200s.is_property_overridable_static(\"%.200s\") not found",
+                            RNA_struct_identifier(self->ptr.type), name);
+               return NULL;
+       }
+
+       return PyBool_FromLong((long)RNA_property_overridable_get(&self->ptr, prop));
+}
+
+PyDoc_STRVAR(pyrna_struct_property_overridable_static_set_doc,
+".. method:: property_overridable_static_set(property)\n"
+"\n"
+"   Define a property as statically overridable or not (only for custom properties!).\n"
+"\n"
+"   :return: True when the overridable status of the property was successfully set.\n"
+"   :rtype: boolean\n"
+);
+static PyObject *pyrna_struct_property_overridable_static_set(BPy_StructRNA *self, PyObject *args)
+{
+       PropertyRNA *prop;
+       const char *name;
+       int is_overridable;
+
+       PYRNA_STRUCT_CHECK_OBJ(self);
+
+       if (!PyArg_ParseTuple(args, "sp:property_overridable_static_set", &name, &is_overridable)) {
+               return NULL;
+       }
+
+       if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
+               PyErr_Format(PyExc_TypeError,
+                            "%.200s.property_overridable_static_set(\"%.200s\") not found",
+                            RNA_struct_identifier(self->ptr.type), name);
+               return NULL;
+       }
+
+       return PyBool_FromLong((long)RNA_property_overridable_static_set(&self->ptr, prop, (bool)is_overridable));
+}
+
+
+
 PyDoc_STRVAR(pyrna_struct_path_resolve_doc,
 ".. method:: path_resolve(path, coerce=True)\n"
 "\n"
@@ -5172,6 +5261,8 @@ static struct PyMethodDef pyrna_struct_methods[] = {
        {"property_unset", (PyCFunction)pyrna_struct_property_unset, METH_VARARGS, pyrna_struct_property_unset_doc},
        {"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc},
        {"is_property_readonly", (PyCFunction)pyrna_struct_is_property_readonly, METH_VARARGS, pyrna_struct_is_property_readonly_doc},
+       {"is_property_overridable_static", (PyCFunction)pyrna_struct_is_property_overridable_static, METH_VARARGS, pyrna_struct_is_property_overridable_static_doc},
+       {"property_overridable_static_set", (PyCFunction)pyrna_struct_property_overridable_static_set, METH_VARARGS, pyrna_struct_property_overridable_static_set_doc},
        {"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
        {"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
        {"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc},
@@ -5581,6 +5672,17 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
                item = NULL;
 
                if (i < pyargs_len) {
+                       /* New in 2.8x, optional arguments must be keywords.  */
+                       if (UNLIKELY((flag_parameter & PARM_REQUIRED) == 0)) {
+                               PyErr_Format(PyExc_TypeError,
+                                            "%.200s.%.200s(): required parameter \"%.200s\" to be a keyword argument!",
+                                            RNA_struct_identifier(self_ptr->type),
+                                            RNA_function_identifier(self_func),
+                                            RNA_property_identifier(parm));
+                               err = -1;
+                               break;
+                       }
+
                        item = PyTuple_GET_ITEM(args, i);
                        kw_arg = false;
                }
@@ -7353,29 +7455,40 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item
 
 static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
 {
+       PyObject *annotations_dict;
        PyObject *item, *key;
-       PyObject *order;
        Py_ssize_t pos = 0;
        int ret = 0;
 
        /* in both cases PyDict_CheckExact(class_dict) will be true even
         * though Operators have a metaclass dict namespace */
+       if ((annotations_dict = PyDict_GetItem(class_dict, bpy_intern_str___annotations__)) &&
+           PyDict_CheckExact(annotations_dict))
+       {
+               while (PyDict_Next(annotations_dict, &pos, &key, &item)) {
+                       ret = deferred_register_prop(srna, key, item);
 
-       if ((order = PyDict_GetItem(class_dict, bpy_intern_str_order)) && PyList_CheckExact(order)) {
-               for (pos = 0; pos < PyList_GET_SIZE(order); pos++) {
-                       key = PyList_GET_ITEM(order, pos);
-                       /* however unlikely its possible
-                        * fails in py 3.3 beta with __qualname__ */
-                       if ((item = PyDict_GetItem(class_dict, key))) {
-                               ret = deferred_register_prop(srna, key, item);
-                               if (ret != 0) {
-                                       break;
-                               }
+                       if (ret != 0) {
+                               break;
                        }
                }
        }
-       else {
+
+       {
+               /* This block can be removed once 2.8x is released and annotations are in use. */
+               bool has_warning = false;
                while (PyDict_Next(class_dict, &pos, &key, &item)) {
+                       if (pyrna_is_deferred_prop(item)) {
+                               if (!has_warning) {
+                                       printf("Warning: class %.200s "
+                                              "contains a properties which should be an annotation!\n",
+                                              RNA_struct_identifier(srna));
+                                       PyC_LineSpit();
+                                       has_warning = true;
+                               }
+                               printf("    make annotation: %.200s.%.200s\n",
+                                      RNA_struct_identifier(srna), _PyUnicode_AsString(key));
+                       }
                        ret = deferred_register_prop(srna, key, item);
 
                        if (ret != 0)
@@ -7658,7 +7771,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
        PyGILState_STATE gilstate;
 
 #ifdef USE_PEDANTIC_WRITE
-       const bool is_readonly_init = !RNA_struct_is_a(ptr->type, &RNA_Operator);
+       const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) ||
+                                       RNA_struct_is_a(ptr->type, &RNA_Gizmo));
        // const char *func_id = RNA_function_identifier(func);  /* UNUSED */
        /* testing, for correctness, not operator and not draw function */
        const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE);
@@ -8316,6 +8430,43 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
        Py_RETURN_NONE;
 }
 
+/* Access to 'owner_id' internal global. */
+
+static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self))
+{
+       const char *name = RNA_struct_state_owner_get();
+       if (name) {
+               return PyUnicode_FromString(name);
+       }
+       Py_RETURN_NONE;
+}
+
+static PyObject *pyrna_bl_owner_id_set(PyObject *UNUSED(self), PyObject *value)
+{
+       const char *name;
+       if (value == Py_None) {
+               name = NULL;
+       }
+       else if (PyUnicode_Check(value)) {
+               name = _PyUnicode_AsString(value);
+       }
+       else {
+               PyErr_Format(PyExc_ValueError,
+                            "owner_set(...): "
+                            "expected None or a string, not '%.200s'", Py_TYPE(value)->tp_name);
+               return NULL;
+       }
+       RNA_struct_state_owner_set(name);
+       Py_RETURN_NONE;
+}
+
+PyMethodDef meth_bpy_owner_id_get = {
+       "_bl_owner_id_get", (PyCFunction)pyrna_bl_owner_id_get, METH_NOARGS, NULL,
+};
+PyMethodDef meth_bpy_owner_id_set = {
+       "_bl_owner_id_set", (PyCFunction)pyrna_bl_owner_id_set, METH_O, NULL,
+};
+
 /* currently this is fairly limited, we would need to make some way to split up
  * pyrna_callback_classmethod_... if we want more than one callback per type */
 typedef struct BPyRNA_CallBack {
@@ -8323,9 +8474,46 @@ typedef struct BPyRNA_CallBack {
        StructRNA   *bpy_srna;
 } PyRNA_CallBack;
 
+PyDoc_STRVAR(pyrna_draw_handler_add_doc,
+".. method:: draw_handler_add(callback, args, region_type, draw_type)\n"
+"\n"
+"   Add a new draw handler to this space type.\n"
+"   It will be called every time the specified region in the space type will be drawn.\n"
+"   Note: All arguments are positional only for now.\n"
+"\n"
+"   :param callback:\n"
+"        A function that will be called when the region is drawn.\n"
+"        It gets the specified arguments as input.\n"
+"   :type callback: function\n"
+"   :param args: Arguments that will be passed to the callback.\n"
+"   :type args: tuple\n"
+"   :param region_type: The region type the callback draws in; usually `'WINDOW'`. (:class:`bpy.types.Region.type`)\n"
+"   :type region_type: str\n"
+"   :param draw_type: Usually `POST_PIXEL` for 2D drawing and `POST_VIEW` for 3D drawing. In some cases `PRE_VIEW` can be used.\n"
+"   :type draw_type: str\n"
+"   :return: Handler that can be removed later on.\n"
+"   :rtype: object"
+);
+
+PyDoc_STRVAR(pyrna_draw_handler_remove_doc,
+".. method:: draw_handler_remove(handler, region_type)\n"
+"\n"
+"   Remove a draw handler that was added previously.\n"
+"\n"
+"   :param handler: The draw handler that should be removed.\n"
+"   :type handler: object\n"
+"   :param region_type: Region type the callback was added to.\n"
+"   :type region_type: str\n"
+);
+
 static struct BPyRNA_CallBack pyrna_cb_methods[] = {
-       {{"draw_handler_add",    (PyCFunction)pyrna_callback_classmethod_add,   METH_VARARGS | METH_STATIC, ""}, &RNA_Space},
-       {{"draw_handler_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_STATIC, ""}, &RNA_Space},
+       {{"draw_handler_add",    (PyCFunction)pyrna_callback_classmethod_add,
+         METH_VARARGS | METH_STATIC, pyrna_draw_handler_add_doc}, &RNA_Space},
+       {{"draw_handler_remove", (PyCFunction)pyrna_callback_classmethod_remove,
+         METH_VARARGS | METH_STATIC, pyrna_draw_handler_remove_doc}, &RNA_Space},
+
+       {{"draw_cursor_add",    (PyCFunction)pyrna_callback_classmethod_add,    METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager},
+       {{"draw_cursor_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager},
        {{NULL, NULL, 0, NULL}, NULL}
 };