Changed the script UI registration to import rather then run each python script,

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.
This commit is contained in:
Campbell Barton 2009-04-11 05:46:40 +00:00
parent c7b587105f
commit 9d922b4c24
8 changed files with 111 additions and 50 deletions

@ -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")

@ -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

@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_util.h"
#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_text.h"
@ -38,10 +39,29 @@ void BPY_free_compiled_text( struct Text *text )
}
}
/*****************************************************************************
* Description: Creates the bpy module and adds it to sys.modules for importing
*****************************************************************************/
static void BPY_init_modules( void )
{
PyObject *mod;
mod = PyModule_New("bpy");
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() );
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;
@ -51,23 +71,11 @@ static PyObject *CreateGlobalDictionary( bContext *C )
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, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
// 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,6 +91,11 @@ 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;
}
@ -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,15 +320,29 @@ 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;
@ -322,22 +352,48 @@ void BPY_run_ui_scripts(bContext *C)
if(!dir)
return;
if (dir != NULL) {
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) {
BLI_make_file_string("/", path, dirname, de->d_name);
/* We could stat the file but easier just to let python
* import it and complain if theres a problem */
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);
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 */
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);
}
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
}

@ -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 );

@ -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);

@ -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);
}

@ -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

@ -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)