Changed the script UI registration to import rather then run each python script,
authorCampbell Barton <ideasman42@gmail.com>
Sat, 11 Apr 2009 05:46:40 +0000 (05:46 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 11 Apr 2009 05:46:40 +0000 (05:46 +0000)
this means it caches the compiled pyc files after importing fro the first time.

My times for importing 501 buttons_objects.py files were.
- running each as a script 1.9sec
- importing for the first time 1.8sec
- importing a second time (using pyc files) 0.57sec

Also added "bpy" to sys.modules so it can be imported.

release/ui/buttons_objects.py
source/blender/python/BPY_extern.h
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_operator.c
source/blender/python/intern/bpy_operator.h
source/blender/python/intern/bpy_rna.c
source/creator/creator.c
source/gameengine/GameLogic/SCA_KeyboardSensor.cpp

index 48c113a84ff45edfe0ccdb50559b106a850c3923..9e4cb9340a41689023bb62a2dd307d00b9fa367c 100644 (file)
@@ -1,3 +1,4 @@
+import bpy
 
 class OBJECT_PT_transform(bpy.types.Panel):
        __label__ = "Transform"
@@ -121,4 +122,3 @@ bpy.ui.addPanel(OBJECT_PT_groups, "BUTTONS_WINDOW", "WINDOW")
 bpy.ui.addPanel(OBJECT_PT_display, "BUTTONS_WINDOW", "WINDOW")
 bpy.ui.addPanel(OBJECT_PT_duplication, "BUTTONS_WINDOW", "WINDOW")
 bpy.ui.addPanel(OBJECT_PT_animation, "BUTTONS_WINDOW", "WINDOW")
-
index f46ef0fa670e7948f72806bbe9a2321f4250a2de..bb22432d90f4d9d0124cd81fad2170df71b622f1 100644 (file)
@@ -99,7 +99,7 @@ extern "C" {
        /* 2.5 UI Scripts */
        int BPY_run_python_script( struct bContext *C, const char *filename, struct Text *text ); // 2.5 working
        int BPY_run_script_space_draw(struct bContext *C, struct SpaceScript * sc); // 2.5 working
-       void BPY_run_ui_scripts(struct bContext *C);
+       void BPY_run_ui_scripts(void);
 //     int BPY_run_script_space_listener(struct bContext *C, struct SpaceScript * sc, struct ARegion *ar, struct wmNotifier *wmn); // 2.5 working
        
        
index 667dd14283f0d1b8bdd545286e8291ea5679829e..db82b740a15997a69003f910764ad8798307a6cf 100644 (file)
@@ -26,6 +26,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_util.h"
+#include "BLI_string.h"
 
 #include "BKE_context.h"
 #include "BKE_text.h"
@@ -39,35 +40,42 @@ void BPY_free_compiled_text( struct Text *text )
 }
 
 /*****************************************************************************
-* Description: This function creates a new Python dictionary object.
+* Description: Creates the bpy module and adds it to sys.modules for importing
 *****************************************************************************/
-
-static PyObject *CreateGlobalDictionary( bContext *C )
+static void BPY_init_modules( void )
 {
        PyObject *mod;
-       PyObject *dict = PyDict_New(  );
-       PyObject *item = PyUnicode_FromString( "__main__" );
-       PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins(  ) );
-       PyDict_SetItemString( dict, "__name__", item );
-       Py_DECREF(item);
        
-       /* add bpy to global namespace */
        mod = PyModule_New("bpy");
-       PyDict_SetItemString( dict, "bpy", mod );
-       Py_DECREF(mod);
        
        PyModule_AddObject( mod, "data", BPY_rna_module() );
        /* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
        PyModule_AddObject( mod, "types", BPY_rna_types() );
-       PyModule_AddObject( mod, "ops", BPY_operator_module(C) );
+       PyModule_AddObject( mod, "ops", BPY_operator_module() );
        PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
        
+       /* add the module so we can import it */
+       PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
+       Py_DECREF(mod);
+}
+
+/*****************************************************************************
+* Description: This function creates a new Python dictionary object.
+*****************************************************************************/
+static PyObject *CreateGlobalDictionary( bContext *C )
+{
+       PyObject *mod;
+       PyObject *dict = PyDict_New(  );
+       PyObject *item = PyUnicode_FromString( "__main__" );
+       PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins(  ) );
+       PyDict_SetItemString( dict, "__name__", item );
+       Py_DECREF(item);
+       
        // XXX - evil, need to access context
        item = PyCObject_FromVoidPtr( C, NULL );
        PyDict_SetItemString( dict, "__bpy_context__", item );
        Py_DECREF(item);
        
-       
        // XXX - put somewhere more logical
        {
                PyMethodDef *ml;
@@ -83,13 +91,18 @@ static PyObject *CreateGlobalDictionary( bContext *C )
                }
        }
        
+       /* add bpy to global namespace */
+       mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
+       PyDict_SetItemString( dict, "bpy", mod );
+       Py_DECREF(mod);
+       
        return dict;
 }
 
 void BPY_start_python( void )
 {
        PyThreadState *py_tstate = NULL;
-
+       
        Py_Initialize(  );
        
        //PySys_SetArgv( argc_copy, argv_copy );
@@ -97,7 +110,10 @@ void BPY_start_python( void )
        /* Initialize thread support (also acquires lock) */
        PyEval_InitThreads();
        
-       // todo - sys paths - our own imports
+       
+       /* bpy.* and lets us import it */
+       BPY_init_modules(); 
+
        
        py_tstate = PyGILState_GetThisThreadState();
        PyEval_ReleaseThread(py_tstate);
@@ -304,16 +320,30 @@ int BPY_run_python_script_space(const char *modulename, const char *func)
 }
 #endif
 
+// #define TIME_REGISTRATION
+
+#ifdef TIME_REGISTRATION
+#include "PIL_time.h"
+#endif
+
 /* XXX this is temporary, need a proper script registration system for 2.5 */
-void BPY_run_ui_scripts(bContext *C)
+void BPY_run_ui_scripts(void)
 {
+#ifdef TIME_REGISTRATION
+       double time = PIL_check_seconds_timer();
+#endif
        DIR *dir; 
        struct dirent *de;
-       struct stat status;
        char *file_extension;
        char path[FILE_MAX];
        char *dirname= BLI_gethome_folder("ui");
-
+       int filelen; /* filename length */
+       
+       PyGILState_STATE gilstate;
+       PyObject *mod;
+       PyObject *sys_path_orig;
+       PyObject *sys_path_new;
+       
        if(!dirname)
                return;
        
@@ -321,23 +351,49 @@ void BPY_run_ui_scripts(bContext *C)
 
        if(!dir)
                return;
-
-       if (dir != NULL) {
-               while((de = readdir(dir)) != NULL) {
-                       BLI_make_file_string("/", path, dirname, de->d_name);
+       
+       gilstate = PyGILState_Ensure();
+       
+       /* backup sys.path */
+       sys_path_orig= PySys_GetObject("path");
+       Py_INCREF(sys_path_orig); /* dont free it */
+       
+       sys_path_new= PyList_New(1);
+       PyList_SET_ITEM(sys_path_new, 0, PyUnicode_FromString(dirname));
+       PySys_SetObject("path", sys_path_new);
+       Py_DECREF(sys_path_new);
+       
+       
+       while((de = readdir(dir)) != NULL) {
+               /* We could stat the file but easier just to let python
+                * import it and complain if theres a problem */
+               
+               file_extension = strstr(de->d_name, ".py");
+               
+               if(file_extension && *(file_extension + 3) == '\0') {
+                       filelen = strlen(de->d_name);
+                       BLI_strncpy(path, de->d_name, filelen-2); /* cut off the .py on copy */
                        
-                       stat(path, &status);
-
-                       /* run if it is a .py file */
-                       if(S_ISREG(status.st_mode)) {
-                               file_extension = strstr(de->d_name, ".py");
-
-                               if(file_extension && *(file_extension + 3) == '\0')
-                                       BPY_run_python_script(C, path, NULL);
+                       mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
+                       if (mod) {
+                               Py_DECREF(mod);                 
+                       }
+                       else {
+                               PyErr_Print();
+                               fprintf(stderr, "unable to import \"%s\"  %s/%s\n", path, dirname, de->d_name);
                        }
+                       
                }
-
-               closedir(dir);
        }
+
+       closedir(dir);
+       
+       PySys_SetObject("path", sys_path_orig);
+       Py_DECREF(sys_path_orig);
+       
+       PyGILState_Release(gilstate);
+#ifdef TIME_REGISTRATION
+       printf("script time %f\n", (PIL_check_seconds_timer()-time));
+#endif
 }
 
index 29ec33767655d7fe0e92729fe170118cd0ef3f97..3e403ea1aad77c893dbf90abd7e41a832c65b413 100644 (file)
@@ -262,7 +262,7 @@ static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname)
 
 PyTypeObject pyop_base_Type = {NULL};
 
-PyObject *BPY_operator_module( bContext *C )
+PyObject *BPY_operator_module( void )
 {
        pyop_base_Type.tp_name = "OperatorBase";
        pyop_base_Type.tp_basicsize = sizeof( BPy_OperatorBase );
index 8eb0b887baa8a3aa2c60f35ef1fe01f8eddb0dfa..c4741f936bfb5d81cf28e2b9a83af91d3a452f2e 100644 (file)
@@ -40,7 +40,7 @@ typedef struct {
        PyObject_HEAD /* required python macro   */
 } BPy_OperatorBase;
 
-PyObject *BPY_operator_module(bContext *C );
+PyObject *BPY_operator_module(void);
 
 /* fill in properties from a python dict */
 int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw);
index 3dc7456de610222b2df2bb55733d2110cc5cf4fc..3f70d914801f95374f328060c01bdf69c93d8fac 100644 (file)
@@ -1526,10 +1526,13 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
                - myClass = type(name='myClass', bases=(myBase,), dict={'some':'value'})
                */
                char name[256], *nameptr;
+               const char *descr= RNA_struct_ui_description(ptr);
 
                PyObject *args = PyTuple_New(3);
                PyObject *bases = PyTuple_New(1);
                PyObject *dict = PyDict_New();
+               PyObject *item;
+               
                
                nameptr= RNA_property_string_get_alloc(ptr, nameprop, name, sizeof(name));
                
@@ -1544,6 +1547,12 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
                PyTuple_SET_ITEM(args, 1, bases);
                
                // arg 3 - add an instance of the rna 
+               if(descr) {
+                       item= PyUnicode_FromString(descr);
+                       PyDict_SetItemString(dict, "__doc__", item);
+                       Py_DECREF(item);
+               }
+               
                PyTuple_SET_ITEM(args, 2, dict); // fill with useful subclass things!
                
                if (PyErr_Occurred()) {
@@ -1552,23 +1561,19 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
                }
                
                newclass = PyObject_CallObject((PyObject *)&PyType_Type, args);
-               // Set this later
-               
+               Py_DECREF(args);
 
                if (newclass) {
-                       PyObject *rna;
                        RNA_struct_py_type_set(ptr->data, (void *)newclass); /* Store for later use */
 
                        /* Not 100% needed but useful,
                         * having an instance within a type looks wrong however this instance IS an rna type */
-                       rna = pyrna_struct_CreatePyObject(ptr);
-                       PyDict_SetItemString(((PyTypeObject *)newclass)->tp_dict, "__rna__", rna);
-                       Py_DECREF(rna);
+                       item = pyrna_struct_CreatePyObject(ptr);
+                       PyDict_SetItemString(((PyTypeObject *)newclass)->tp_dict, "__rna__", item);
+                       Py_DECREF(item);
                        /* done with rna instance */
                }
                
-               Py_DECREF(args);
-               
                if (name != nameptr)
                        MEM_freeN(nameptr);
        }
index 082f2395b3f442c44a7a8590b514d5a14e545a1b..cb1fc18248f934b6342be788d85e4ec11d0fce46 100644 (file)
@@ -529,7 +529,7 @@ int main(int argc, char **argv)
         */
        BPY_post_start_python();
 
-       BPY_run_ui_scripts(C);
+       BPY_run_ui_scripts();
 #endif
        
 #ifdef WITH_QUICKTIME
index 324e5eae98a624298bb00cf85dc6f71f3acc245e..ca30382b8c0c49afe52622f32174db4c601e1596 100644 (file)
@@ -148,7 +148,7 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
                bool justreleased = false;
                bool active = false;
 
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        switch (inevent.m_status) 
@@ -528,7 +528,7 @@ void SCA_KeyboardSensor::LogKeystrokes(void)
                int index = 0;
                /* Check on all keys whether they were pushed. This does not
          * untangle the ordering, so don't type too fast :) */
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        if (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED) //NO_INPUTSTATUS)
@@ -663,7 +663,7 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, P
                
                int index = 0;
                
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        if ((inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)
@@ -704,7 +704,7 @@ SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice();
        {
                int index = 0;
                
-               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+               for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
                {
                        const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                        if ( (inevent.m_status == SCA_InputEvent::KX_ACTIVE)
@@ -737,7 +737,7 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_KeyboardSensor, getEventList,
 
        PyObject* resultlist = PyList_New(0);
        
-       for (int i=SCA_IInputDevice::KX_BEGINKEY ; i< SCA_IInputDevice::KX_ENDKEY;i++)
+       for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++)
        {
                const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i);
                if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)