Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2011-10-01 21:54:33 +0400
committerCampbell Barton <ideasman42@gmail.com>2011-10-01 21:54:33 +0400
commit9a88524f681d62cee51dfbc3186d59b4b0712a05 (patch)
tree8fc1c2e8d81aac974e39d14d409f8c338530095b /source/blender/python
parent738491555d4e831186de337800dce4f14c56d252 (diff)
support for object data material assignment in python
eg: bpy.context.object.data.materials[0] = bpy.data.materials["SomeMaterial"]
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/intern/bpy_rna.c175
1 files changed, 162 insertions, 13 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index d367ea92cf4..d5a950fc5bb 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1922,6 +1922,21 @@ static int pyrna_prop_collection_bool(BPy_PropertyRNA *self)
return test;
}
+
+#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \
+ /* notice getting the length of the collection is avoided unless negative \
+ * index is used or to detect internal error with a valid index. \
+ * This is done for faster lookups. */ \
+ if(keynum < 0) { \
+ keynum_abs += RNA_property_collection_length(&self->ptr, self->prop); \
+ if(keynum_abs < 0) { \
+ PyErr_Format(PyExc_IndexError, \
+ "bpy_prop_collection[%d]: out of range.", keynum); \
+ return ret_err; \
+ } \
+ } \
+
+
/* internal use only */
static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum)
{
@@ -1930,17 +1945,7 @@ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_s
PYRNA_PROP_CHECK_OBJ(self)
- /* notice getting the length of the collection is avoided unless negative index is used
- * or to detect internal error with a valid index.
- * This is done for faster lookups. */
- if(keynum < 0) {
- keynum_abs += RNA_property_collection_length(&self->ptr, self->prop);
-
- if(keynum_abs < 0) {
- PyErr_Format(PyExc_IndexError, "bpy_prop_collection[%d]: out of range.", keynum);
- return NULL;
- }
- }
+ PYRNA_PROP_COLLECTION_ABS_INDEX(NULL);
if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) {
return pyrna_struct_CreatePyObject(&newptr);
@@ -1963,6 +1968,28 @@ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_s
}
}
+/* values type must have been already checked */
+static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum, PyObject *value)
+{
+ Py_ssize_t keynum_abs= keynum;
+ const PointerRNA *ptr= (value == Py_None) ? (&PointerRNA_NULL) : &((BPy_StructRNA *)value)->ptr;
+
+ PYRNA_PROP_CHECK_INT(self)
+
+ PYRNA_PROP_COLLECTION_ABS_INDEX(-1);
+
+ if(RNA_property_collection_assign_int(&self->ptr, self->prop, keynum_abs, ptr) == 0) {
+
+ PyErr_Format(PyExc_IndexError,
+ "bpy_prop_collection[index] = value: "
+ "failed assignment (unknown reason)", keynum);
+
+ return -1;
+ }
+
+ return 0;
+}
+
static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, int keynum)
{
int len;
@@ -2173,6 +2200,128 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject
}
}
+/* generic check to see if a PyObject is compatible with a collection
+ * -1 on failier, 0 on success, sets the error */
+static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *value)
+{
+ StructRNA *prop_srna;
+
+ if(value == Py_None) {
+ if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "bpy_prop_collection[key] = value: invalid, "
+ "this collection doesnt support None assignment");
+ return -1;
+ }
+ else {
+ return 0; /* None is OK */
+ }
+ }
+ else if (BPy_StructRNA_Check(value) == 0) {
+ PyErr_Format(PyExc_TypeError,
+ "bpy_prop_collection[key] = value: invalid, "
+ "expected a StructRNA type or None, not a %.200s",
+ Py_TYPE(value)->tp_name);
+ return -1;
+ }
+ else if((prop_srna= RNA_property_pointer_type(&self->ptr, self->prop))) {
+ StructRNA *value_srna= ((BPy_StructRNA *)value)->ptr.type;
+ if (RNA_struct_is_a(value_srna, prop_srna) == 0) {
+ PyErr_Format(PyExc_TypeError,
+ "bpy_prop_collection[key] = value: invalid, "
+ "expected a '%.200s' type or None, not a '%.200s'",
+ RNA_struct_identifier(prop_srna),
+ RNA_struct_identifier(value_srna)
+ );
+ return -1;
+ }
+ else {
+ return 0; /* OK, this is the correct type!*/
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "bpy_prop_collection[key] = value: internal error, "
+ "failed to get the collection type");
+ return -1;
+}
+
+/* note: currently this is a copy of 'pyrna_prop_collection_subscript' with
+ * large blocks commented, we may support slice/key indicies later */
+static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject *key, PyObject *value)
+{
+ PYRNA_PROP_CHECK_INT(self);
+
+ /* validate the assigned value */
+ if(value == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "del bpy_prop_collection[key]: not supported");
+ return -1;
+ }
+ else if (pyrna_prop_collection_type_check(self, value) == -1) {
+ return -1; /* exception is set */
+ }
+
+#if 0
+ if (PyUnicode_Check(key)) {
+ return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key));
+ }
+ else
+#endif
+ if (PyIndex_Check(key)) {
+ Py_ssize_t i= PyNumber_AsSsize_t(key, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return -1;
+
+ return pyrna_prop_collection_ass_subscript_int(self, i, value);
+ }
+#if 0 /* TODO, fake slice assignment */
+ else if (PySlice_Check(key)) {
+ PySliceObject *key_slice= (PySliceObject *)key;
+ Py_ssize_t step= 1;
+
+ if(key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
+ return NULL;
+ }
+ else if (step != 1) {
+ PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported");
+ return NULL;
+ }
+ else if(key_slice->start == Py_None && key_slice->stop == Py_None) {
+ return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
+ }
+ else {
+ Py_ssize_t start= 0, stop= PY_SSIZE_T_MAX;
+
+ /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
+ if(key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
+ if(key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL;
+
+ if(start < 0 || stop < 0) {
+ /* only get the length for negative values */
+ Py_ssize_t len= (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop);
+ if(start < 0) start += len;
+ if(stop < 0) start += len;
+ }
+
+ if (stop - start <= 0) {
+ return PyList_New(0);
+ }
+ else {
+ return pyrna_prop_collection_subscript_slice(self, start, stop);
+ }
+ }
+ }
+#endif
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "bpy_prop_collection[key]: invalid key, "
+ "must be a string or an int, not %.200s",
+ Py_TYPE(key)->tp_name);
+ return -1;
+ }
+}
+
static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject *key)
{
PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self)
@@ -2409,7 +2558,7 @@ static PyMappingMethods pyrna_prop_array_as_mapping= {
static PyMappingMethods pyrna_prop_collection_as_mapping= {
(lenfunc) pyrna_prop_collection_length, /* mp_length */
(binaryfunc) pyrna_prop_collection_subscript, /* mp_subscript */
- (objobjargproc) NULL, /* mp_ass_subscript */
+ (objobjargproc) pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */
};
/* only for fast bool's, large structs, assign nb_bool on init */
@@ -2505,7 +2654,7 @@ static PySequenceMethods pyrna_prop_collection_as_sequence= {
NULL, /* sq_repeat */
(ssizeargfunc)pyrna_prop_collection_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
NULL, /* *was* sq_slice */
- NULL, /* sq_ass_item */
+ (ssizeobjargproc)/* pyrna_prop_collection_ass_subscript_int */ NULL /* let mapping take this one */, /* sq_ass_item */
NULL, /* *was* sq_ass_slice */
(objobjproc)pyrna_prop_collection_contains, /* sq_contains */
(binaryfunc) NULL, /* sq_inplace_concat */