Changed the script UI registration to import rather then run each python script,
[blender-staging.git] / source / blender / python / intern / bpy_interface.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/stat.h>
6
7 #ifndef WIN32
8 #include <dirent.h>
9 #else
10 #include "BLI_winstuff.h"
11 #endif
12
13 #include <Python.h>
14 #include "compile.h"            /* for the PyCodeObject */
15 #include "eval.h"               /* for PyEval_EvalCode */
16
17 #include "bpy_compat.h"
18
19 #include "bpy_rna.h"
20 #include "bpy_operator.h"
21 #include "bpy_ui.h"
22
23 #include "DNA_space_types.h"
24 #include "DNA_text_types.h"
25
26 #include "MEM_guardedalloc.h"
27
28 #include "BLI_util.h"
29 #include "BLI_string.h"
30
31 #include "BKE_context.h"
32 #include "BKE_text.h"
33
34 void BPY_free_compiled_text( struct Text *text )
35 {
36         if( text->compiled ) {
37                 Py_DECREF( ( PyObject * ) text->compiled );
38                 text->compiled = NULL;
39         }
40 }
41
42 /*****************************************************************************
43 * Description: Creates the bpy module and adds it to sys.modules for importing
44 *****************************************************************************/
45 static void BPY_init_modules( void )
46 {
47         PyObject *mod;
48         
49         mod = PyModule_New("bpy");
50         
51         PyModule_AddObject( mod, "data", BPY_rna_module() );
52         /* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
53         PyModule_AddObject( mod, "types", BPY_rna_types() );
54         PyModule_AddObject( mod, "ops", BPY_operator_module() );
55         PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
56         
57         /* add the module so we can import it */
58         PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
59         Py_DECREF(mod);
60 }
61
62 /*****************************************************************************
63 * Description: This function creates a new Python dictionary object.
64 *****************************************************************************/
65 static PyObject *CreateGlobalDictionary( bContext *C )
66 {
67         PyObject *mod;
68         PyObject *dict = PyDict_New(  );
69         PyObject *item = PyUnicode_FromString( "__main__" );
70         PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins(  ) );
71         PyDict_SetItemString( dict, "__name__", item );
72         Py_DECREF(item);
73         
74         // XXX - evil, need to access context
75         item = PyCObject_FromVoidPtr( C, NULL );
76         PyDict_SetItemString( dict, "__bpy_context__", item );
77         Py_DECREF(item);
78         
79         // XXX - put somewhere more logical
80         {
81                 PyMethodDef *ml;
82                 static PyMethodDef bpy_prop_meths[] = {
83                         {"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
84                         {"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
85                         {"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
86                         {NULL, NULL, 0, NULL}
87                 };
88                 
89                 for(ml = bpy_prop_meths; ml->ml_name; ml++) {
90                         PyDict_SetItemString( dict, ml->ml_name, PyCFunction_New(ml, NULL));
91                 }
92         }
93         
94         /* add bpy to global namespace */
95         mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
96         PyDict_SetItemString( dict, "bpy", mod );
97         Py_DECREF(mod);
98         
99         return dict;
100 }
101
102 void BPY_start_python( void )
103 {
104         PyThreadState *py_tstate = NULL;
105         
106         Py_Initialize(  );
107         
108         //PySys_SetArgv( argc_copy, argv_copy );
109         
110         /* Initialize thread support (also acquires lock) */
111         PyEval_InitThreads();
112         
113         
114         /* bpy.* and lets us import it */
115         BPY_init_modules(); 
116
117         
118         py_tstate = PyGILState_GetThisThreadState();
119         PyEval_ReleaseThread(py_tstate);
120         
121 }
122
123 void BPY_end_python( void )
124 {
125         PyGILState_Ensure(); /* finalizing, no need to grab the state */
126         
127         // free other python data.
128         //BPY_rna_free_types();
129         
130         Py_Finalize(  );
131         
132         return;
133 }
134
135 /* Can run a file or text block */
136 int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
137 {
138         PyObject *py_dict, *py_result;
139         PyGILState_STATE gilstate;
140         
141         if (fn==NULL && text==NULL) {
142                 return 0;
143         }
144         
145         //BPY_start_python();
146         
147         gilstate = PyGILState_Ensure();
148
149         py_dict = CreateGlobalDictionary(C);
150
151         if (text) {
152                 
153                 if( !text->compiled ) { /* if it wasn't already compiled, do it now */
154                         char *buf = txt_to_buf( text );
155
156                         text->compiled =
157                                 Py_CompileString( buf, text->id.name+2, Py_file_input );
158
159                         MEM_freeN( buf );
160
161                         if( PyErr_Occurred(  ) ) {
162                                 PyErr_Print();
163                                 BPY_free_compiled_text( text );
164                                 PyGILState_Release(gilstate);
165                                 return 0;
166                         }
167                 }
168                 py_result =  PyEval_EvalCode( text->compiled, py_dict, py_dict );
169                 
170         } else {
171                 char pystring[512];
172                 /* TODO - look into a better way to run a file */
173                 sprintf(pystring, "exec(open(r'%s').read())", fn);      
174                 py_result = PyRun_String( pystring, Py_file_input, py_dict, py_dict );                  
175         }
176         
177         if (!py_result) {
178                 PyErr_Print();
179         } else {
180                 Py_DECREF( py_result );
181         }
182         PyGILState_Release(gilstate);
183         
184         //BPY_end_python();
185         return py_result ? 1:0;
186 }
187
188
189 /* TODO - move into bpy_space.c ? */
190 /* GUI interface routines */
191
192 /* Copied from Draw.c */
193 static void exit_pydraw( SpaceScript * sc, short err )
194 {
195         Script *script = NULL;
196
197         if( !sc || !sc->script )
198                 return;
199
200         script = sc->script;
201
202         if( err ) {
203                 PyErr_Print(  );
204                 script->flags = 0;      /* mark script struct for deletion */
205                 SCRIPT_SET_NULL(script);
206                 script->scriptname[0] = '\0';
207                 script->scriptarg[0] = '\0';
208 // XXX 2.5              error_pyscript();
209 // XXX 2.5              scrarea_queue_redraw( sc->area );
210         }
211
212 #if 0 // XXX 2.5
213         BPy_Set_DrawButtonsList(sc->but_refs);
214         BPy_Free_DrawButtonsList(); /*clear all temp button references*/
215 #endif
216
217         sc->but_refs = NULL;
218         
219         Py_XDECREF( ( PyObject * ) script->py_draw );
220         Py_XDECREF( ( PyObject * ) script->py_event );
221         Py_XDECREF( ( PyObject * ) script->py_button );
222
223         script->py_draw = script->py_event = script->py_button = NULL;
224 }
225
226 static int bpy_run_script_init(bContext *C, SpaceScript * sc)
227 {
228         if (sc->script==NULL) 
229                 return 0;
230         
231         if (sc->script->py_draw==NULL && sc->script->scriptname[0] != '\0')
232                 BPY_run_python_script(C, sc->script->scriptname, NULL);
233                 
234         if (sc->script->py_draw==NULL)
235                 return 0;
236         
237         return 1;
238 }
239
240 int BPY_run_script_space_draw(bContext *C, SpaceScript * sc)
241 {
242         if (bpy_run_script_init(C, sc)) {
243                 PyGILState_STATE gilstate = PyGILState_Ensure();
244                 PyObject *result = PyObject_CallObject( sc->script->py_draw, NULL );
245                 
246                 if (result==NULL)
247                         exit_pydraw(sc, 1);
248                         
249                 PyGILState_Release(gilstate);
250         }
251         return 1;
252 }
253
254 // XXX - not used yet, listeners dont get a context
255 int BPY_run_script_space_listener(bContext *C, SpaceScript * sc)
256 {
257         if (bpy_run_script_init(C, sc)) {
258                 PyGILState_STATE gilstate = PyGILState_Ensure();
259                 
260                 PyObject *result = PyObject_CallObject( sc->script->py_draw, NULL );
261                 
262                 if (result==NULL)
263                         exit_pydraw(sc, 1);
264                         
265                 PyGILState_Release(gilstate);
266         }
267         return 1;
268 }
269
270 void BPY_DECREF(void *pyob_ptr)
271 {
272         Py_DECREF((PyObject *)pyob_ptr);
273 }
274
275 #if 0
276 /* called from the the scripts window, assume context is ok */
277 int BPY_run_python_script_space(const char *modulename, const char *func)
278 {
279         PyObject *py_dict, *py_result= NULL;
280         char pystring[512];
281         PyGILState_STATE gilstate;
282         
283         /* for calling the module function */
284         PyObject *py_func, 
285         
286         gilstate = PyGILState_Ensure();
287         
288         py_dict = CreateGlobalDictionary(C);
289         
290         PyObject *module = PyImport_ImportModule(scpt->script.filename);
291         if (module==NULL) {
292                 PyErr_SetFormat(PyExc_SystemError, "could not import '%s'", scpt->script.filename);
293         }
294         else {
295                 py_func = PyObject_GetAttrString(modulename, func);
296                 if (py_func==NULL) {
297                         PyErr_SetFormat(PyExc_SystemError, "module has no function '%s.%s'\n", scpt->script.filename, func);
298                 }
299                 else {
300                         Py_DECREF(py_func);
301                         if (!PyCallable_Check(py_func)) {
302                                 PyErr_SetFormat(PyExc_SystemError, "module item is not callable '%s.%s'\n", scpt->script.filename, func);
303                         }
304                         else {
305                                 py_result= PyObject_CallObject(py_func, NULL); // XXX will need args eventually
306                         }
307                 }
308         }
309         
310         if (!py_result)
311                 PyErr_Print();
312         else
313                 Py_DECREF( py_result );
314         
315         Py_XDECREF(module);
316         
317         
318         PyGILState_Release(gilstate);
319         return 1;
320 }
321 #endif
322
323 // #define TIME_REGISTRATION
324
325 #ifdef TIME_REGISTRATION
326 #include "PIL_time.h"
327 #endif
328
329 /* XXX this is temporary, need a proper script registration system for 2.5 */
330 void BPY_run_ui_scripts(void)
331 {
332 #ifdef TIME_REGISTRATION
333         double time = PIL_check_seconds_timer();
334 #endif
335         DIR *dir; 
336         struct dirent *de;
337         char *file_extension;
338         char path[FILE_MAX];
339         char *dirname= BLI_gethome_folder("ui");
340         int filelen; /* filename length */
341         
342         PyGILState_STATE gilstate;
343         PyObject *mod;
344         PyObject *sys_path_orig;
345         PyObject *sys_path_new;
346         
347         if(!dirname)
348                 return;
349         
350         dir = opendir(dirname);
351
352         if(!dir)
353                 return;
354         
355         gilstate = PyGILState_Ensure();
356         
357         /* backup sys.path */
358         sys_path_orig= PySys_GetObject("path");
359         Py_INCREF(sys_path_orig); /* dont free it */
360         
361         sys_path_new= PyList_New(1);
362         PyList_SET_ITEM(sys_path_new, 0, PyUnicode_FromString(dirname));
363         PySys_SetObject("path", sys_path_new);
364         Py_DECREF(sys_path_new);
365         
366         
367         while((de = readdir(dir)) != NULL) {
368                 /* We could stat the file but easier just to let python
369                  * import it and complain if theres a problem */
370                 
371                 file_extension = strstr(de->d_name, ".py");
372                 
373                 if(file_extension && *(file_extension + 3) == '\0') {
374                         filelen = strlen(de->d_name);
375                         BLI_strncpy(path, de->d_name, filelen-2); /* cut off the .py on copy */
376                         
377                         mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
378                         if (mod) {
379                                 Py_DECREF(mod);                 
380                         }
381                         else {
382                                 PyErr_Print();
383                                 fprintf(stderr, "unable to import \"%s\"  %s/%s\n", path, dirname, de->d_name);
384                         }
385                         
386                 }
387         }
388
389         closedir(dir);
390         
391         PySys_SetObject("path", sys_path_orig);
392         Py_DECREF(sys_path_orig);
393         
394         PyGILState_Release(gilstate);
395 #ifdef TIME_REGISTRATION
396         printf("script time %f\n", (PIL_check_seconds_timer()-time));
397 #endif
398 }
399