Change to how python classes are initialized when blender calls them.
authorCampbell Barton <ideasman42@gmail.com>
Thu, 17 Feb 2011 07:21:44 +0000 (07:21 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 17 Feb 2011 07:21:44 +0000 (07:21 +0000)
Annoyance was that operators that defined and __init__ function would need to do...
    def __init__(self, another_self):
        ....

py/rna was calling the class directly with PyObject_Call() but needed to pass the pre-allocated object only so __init__() would run .
This works OK internally but becomes messy since __new__ and __init__ always get the same args there was no way to avoid a superfluous self argument to __init__.

source/blender/python/intern/bpy_rna.c

index d1bf11927089f1ab694687cc03b436f1b00f6542..c0baf0890946110021e05bcbae3e9343e89cbcdf 100644 (file)
@@ -5396,7 +5396,8 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
 static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
 {
        PyObject *args;
-       PyObject *ret= NULL, *py_srna= NULL, *py_class, *py_class_instance= NULL, *parmitem;
+       PyObject *ret= NULL, *py_srna= NULL, *py_class_instance= NULL, *parmitem;
+       PyTypeObject *py_class;
        void **py_class_instance_store= NULL;
        PropertyRNA *parm;
        ParameterIterator iter;
@@ -5461,6 +5462,25 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
                        py_class_instance = NULL;
                }
                else {
+#if 1
+                       /* Skip the code below and call init directly on the allocated 'py_srna'
+                        * otherwise __init__() always needs to take a second self argument, see pyrna_struct_new().
+                        * Although this is annoying to have to impliment a part of pythons typeobject.c:type_call().
+                        */
+                       if(py_class->tp_init) {
+                               /* true in most cases even when the class its self doesnt define an __init__ function. */
+                               args = PyTuple_New(0);
+                       if (py_class->tp_init(py_srna, args, NULL) < 0) {
+                           Py_DECREF(py_srna);
+                           py_srna= NULL;
+                                       /* err set below */
+                               }
+                               Py_DECREF(args);
+                       }
+
+                       py_class_instance= py_srna;
+
+#else
                        /* 'almost' all the time calling the class isnt needed.
                         * We could just do...
                        py_class_instance = py_srna;
@@ -5473,7 +5493,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
                        PyTuple_SET_ITEM(args, 0, py_srna);
                        py_class_instance= PyObject_Call(py_class, args, NULL);
                        Py_DECREF(args);
-                       
+
+#endif         
                        if(py_class_instance == NULL) {
                                err= -1; /* so the error is not overridden below */
                        }
@@ -5485,7 +5506,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
        }
 
        if (err != -1 && (is_static || py_class_instance)) { /* Initializing the class worked, now run its invoke function */
-               PyObject *item= PyObject_GetAttrString(py_class, RNA_function_identifier(func));
+               PyObject *item= PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func));
 //             flag= RNA_function_flag(func);
 
                if(item) {