[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17635] branches/blender2.5/blender/source /blender/python/intern/bpy_rna.c: PyRNA

Campbell Barton ideasman42 at gmail.com
Sun Nov 30 04:52:08 CET 2008


Revision: 17635
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17635
Author:   campbellbarton
Date:     2008-11-30 04:52:07 +0100 (Sun, 30 Nov 2008)

Log Message:
-----------
PyRNA
Can now assign RNA arrays from python lists of bools/ints/floats
 eg -> rna.scenes["Scene"].layer = [True] * 20

Also added exceptions when trying to set readonly properties.
 

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c	2008-11-30 02:30:34 UTC (rev 17634)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c	2008-11-30 03:52:07 UTC (rev 17635)
@@ -131,111 +131,198 @@
 
 static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value)
 {
-	int ret = 0;
 	int type = RNA_property_type(ptr, prop);
 	int len = RNA_property_array_length(ptr, prop);
 	/* resolve path */
 	
 	if (len > 0) {
-		/* resolve the array from a new pytype */
-		PyErr_SetString(PyExc_TypeError, "array type, cant assign");
-		return -1;
-	}
-	
-	/* see if we can coorce into a python type - PropertyType */
-	switch (type) {
-	case PROP_BOOLEAN:
-	{
-		int param = PyObject_IsTrue( value );
+		PyObject *item;
+		int i;
 		
-		if( param == -1 ) {
-			PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1");
-			ret = -1;
-		} else {
-			RNA_property_boolean_set(ptr, prop, param);
+		if (!PySequence_Check(value)) {
+			PyErr_SetString(PyExc_TypeError, "expected a python sequence type assigned to an RNA array.");
+			return -1;
 		}
-		break;
-	}
-	case PROP_INT:
-	{
-		int param = PyLong_AsSsize_t(value);
-		if (PyErr_Occurred()) {
-			PyErr_SetString(PyExc_TypeError, "expected an int type");
-			ret = -1;
-		} else {
-			RNA_property_int_set(ptr, prop, param);
+		
+		if ((int)PySequence_Length(value) != len) {
+			PyErr_SetString(PyExc_AttributeError, "python sequence length did not match the RNA array.");
+			return -1;
 		}
-		break;
-	}
-	case PROP_FLOAT:
-	{
-		float param = PyFloat_AsDouble(value);
-		if (PyErr_Occurred()) {
-			PyErr_SetString(PyExc_TypeError, "expected a float type");
-			ret = -1;
-		} else {
-			RNA_property_float_set(ptr, prop, param);
-		}
-		break;
-	}
-	case PROP_STRING:
-	{
-		char *param = _PyUnicode_AsString(value);
 		
-		if (param==NULL) {
-			PyErr_SetString(PyExc_TypeError, "expected a string type");
-			ret = -1;
-		} else {
-			RNA_property_string_set(ptr, prop, param);
+		/* for arrays we have a limited number of types */
+		switch (type) {
+		case PROP_BOOLEAN:
+		{
+			signed char *param_arr = MEM_mallocN(sizeof(char) * len, "pyrna bool array");
+			
+			/* collect the variables before assigning, incase one of them is incorrect */
+			for (i=0; i<len; i++) {
+				item = PySequence_GetItem(value, i);
+				param_arr[i] = PyObject_IsTrue( item );
+				Py_DECREF(item);
+				
+				if (param_arr[i] < 0) {
+					MEM_freeN(param_arr);
+					PyErr_SetString(PyExc_AttributeError, "one or more of the values in the sequence is not a boolean");
+					return -1;
+				}
+			}
+			
+			for (i=0; i<len; i++) {
+				RNA_property_boolean_set_array(ptr, prop, i, param_arr[i]);
+			}
+			
+			MEM_freeN(param_arr);
+			break;
 		}
-		break;
-	}
-	case PROP_ENUM:
-	{
-		char *param = _PyUnicode_AsString(value);
+		case PROP_INT:
+		{
+			int *param_arr = MEM_mallocN(sizeof(int) * len, "pyrna int array");
+			
+			/* collect the variables before assigning, incase one of them is incorrect */
+			for (i=0; i<len; i++) {
+				item = PySequence_GetItem(value, i);
+				param_arr[i] = (int)PyLong_AsSsize_t(item); /* deal with any errors later */
+				Py_DECREF(item);
+			}
+			
+			if (PyErr_Occurred()) {
+				MEM_freeN(param_arr);
+				PyErr_SetString(PyExc_AttributeError, "one or more of the values in the sequence could not be used as an int");
+				return -1;
+			}
+			
+			for (i=0; i<len; i++) {
+				RNA_property_int_set_array(ptr, prop, i, param_arr[i]);
+			}
+			
+			MEM_freeN(param_arr);
+			break;
+		}
+		case PROP_FLOAT:
+		{
+			float *param_arr = MEM_mallocN(sizeof(float) * len, "pyrna float array");
+			
+			/* collect the variables before assigning, incase one of them is incorrect */
+			for (i=0; i<len; i++) {
+				item = PySequence_GetItem(value, i);
+				param_arr[i] = (float)PyFloat_AsDouble(item); /* deal with any errors later */
+				Py_DECREF(item);
+			}
+			
+			if (PyErr_Occurred()) {
+				MEM_freeN(param_arr);
+				PyErr_SetString(PyExc_AttributeError, "one or more of the values in the sequence could not be used as a float");
+				return -1;
+			}
+			
+			for (i=0; i<len; i++) {
+				RNA_property_float_set_array(ptr, prop, i, param_arr[i]);
+			}
+			
+			MEM_freeN(param_arr);
+			break;
+		}
+		}
+	} else {
+		/* Normal Property (not an array) */
 		
-		if (param==NULL) {
-			PyErr_SetString(PyExc_TypeError, "expected a string type");
-			ret = -1;
-		} else {
-			const EnumPropertyItem *item;
-			int totitem, i, val;
+		/* see if we can coorce into a python type - PropertyType */
+		switch (type) {
+		case PROP_BOOLEAN:
+		{
+			int param = PyObject_IsTrue( value );
 			
-			RNA_property_enum_items(ptr, prop, &item, &totitem);
+			if( param < 0 ) {
+				PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1");
+				return -1;
+			} else {
+				RNA_property_boolean_set(ptr, prop, param);
+			}
+			break;
+		}
+		case PROP_INT:
+		{
+			int param = PyLong_AsSsize_t(value);
+			if (PyErr_Occurred()) {
+				PyErr_SetString(PyExc_TypeError, "expected an int type");
+				return -1;
+			} else {
+				RNA_property_int_set(ptr, prop, param);
+			}
+			break;
+		}
+		case PROP_FLOAT:
+		{
+			float param = PyFloat_AsDouble(value);
+			if (PyErr_Occurred()) {
+				PyErr_SetString(PyExc_TypeError, "expected a float type");
+				return -1;
+			} else {
+				RNA_property_float_set(ptr, prop, param);
+			}
+			break;
+		}
+		case PROP_STRING:
+		{
+			char *param = _PyUnicode_AsString(value);
 			
-			for (i=0; i<totitem; i++) {
-				if (strcmp(item[i].identifier, param)==0) {
-					val = item[i].value;
-					break;
-				}
+			if (param==NULL) {
+				PyErr_SetString(PyExc_TypeError, "expected a string type");
+				return -1;
+			} else {
+				RNA_property_string_set(ptr, prop, param);
 			}
+			break;
+		}
+		case PROP_ENUM:
+		{
+			char *param = _PyUnicode_AsString(value);
 			
-			if (i<totitem) {
-				RNA_property_enum_set(ptr, prop, val);
+			if (param==NULL) {
+				PyErr_SetString(PyExc_TypeError, "expected a string type");
+				return -1;
 			} else {
-				PyErr_Format(PyExc_AttributeError, "enum \"%s\" not found", param);
-				ret = -1;
+				const EnumPropertyItem *item;
+				int totitem, i, val;
+				
+				RNA_property_enum_items(ptr, prop, &item, &totitem);
+				
+				for (i=0; i<totitem; i++) {
+					if (strcmp(item[i].identifier, param)==0) {
+						val = item[i].value;
+						break;
+					}
+				}
+				
+				if (i<totitem) {
+					RNA_property_enum_set(ptr, prop, val);
+				} else {
+					PyErr_Format(PyExc_AttributeError, "enum \"%s\" not found", param);
+					return -1;
+				}
 			}
+			
+			break;
 		}
-		
-		break;
+		case PROP_POINTER:
+		{
+			PyErr_SetString(PyExc_AttributeError, "cant assign pointers yet");
+			return -1;
+			break;
+		}
+		case PROP_COLLECTION:
+			PyErr_SetString(PyExc_AttributeError, "cant assign to collections");
+			return -1;
+			break;
+		default:
+			PyErr_SetString(PyExc_AttributeError, "unknown property type (pyrna_py_to_prop)");
+			return -1;
+			break;
+		}
 	}
-	case PROP_POINTER:
-	{
-		PyErr_SetString(PyExc_AttributeError, "cant assign pointers yet");
-		ret = -1;
-		break;
-	}
-	case PROP_COLLECTION:
-		PyErr_SetString(PyExc_AttributeError, "cant assign to collections");
-		break;
-	default:
-		PyErr_SetString(PyExc_AttributeError, "unknown property type (pyrna_py_to_prop)");
-		ret = -1;
-		break;
-	}
 	
-	return ret;
+	return 0;
 }
 
 
@@ -279,7 +366,7 @@
 	{
 		int param = PyObject_IsTrue( value );
 		
-		if( param == -1 ) {
+		if( param < 0 ) {
 			PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1");
 			ret = -1;
 		} else {
@@ -394,6 +481,11 @@
 	int keynum;
 	char *keyname = NULL;
 	
+	if (!RNA_property_editable(&self->ptr, self->prop)) {
+		PyErr_Format( PyExc_AttributeError, "Attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(&self->ptr, self->prop), RNA_struct_identifier(&self->ptr) );
+		return -1;
+	}
+	
 	if (PyUnicode_Check(key)) {
 		keyname = _PyUnicode_AsString(key);
 	} else if (PyLong_Check(key)) {
@@ -480,20 +572,20 @@
 //--------------- setattr-------------------------------------------
 static int pyrna_struct_setattr( BPy_StructRNA * self, char *name, PyObject * value )
 {
-	int ret = 0;
-	PropertyRNA *prop;
+	PropertyRNA *prop = RNA_struct_find_property(&self->ptr, name);
 	
-	prop = RNA_struct_find_property(&self->ptr, name);
-	
 	if (prop==NULL) {
 		PyErr_Format( PyExc_AttributeError, "Attribute \"%s\" not found", name);
-		ret = -1;
-	} else {
-		/* pyrna_py_to_prop sets its own exceptions */
-		ret = pyrna_py_to_prop(&self->ptr, prop, value);
+		return -1;
+	}		
+	
+	if (!RNA_property_editable(&self->ptr, prop)) {
+		PyErr_Format( PyExc_AttributeError, "Attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(&self->ptr, prop), RNA_struct_identifier(&self->ptr) );
+		return -1;
 	}
-	
-	return ret;
+		
+	/* pyrna_py_to_prop sets its own exceptions */
+	return pyrna_py_to_prop(&self->ptr, prop, value);
 }
 
 





More information about the Bf-blender-cvs mailing list