3 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version. The Blender
9 * Foundation also sells licenses for use in proprietary software under
10 * the Blender License. See http://www.blender.org/BL/ for information
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23 * All rights reserved.
25 * This is a new part of Blender.
27 * Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney
29 * ***** END GPL/BL DUAL LICENSE BLOCK *****
36 #include "compile.h" /* for the PyCodeObject */
37 #include "eval.h" /* for PyEval_EvalCode */
41 #include <MEM_guardedalloc.h>
42 #include <BLI_blenlib.h> /* for BLI_last_slash() */
44 #include <BIF_interface.h> /* for pupmenu */
45 #include <BIF_space.h>
46 #include <BIF_screen.h>
47 #include <BIF_toolbox.h>
48 #include <BKE_global.h>
49 #include <BKE_library.h>
52 #include <BKE_utildefines.h>
53 #include <BPI_script.h>
55 #include <DNA_camera_types.h>
57 #include <DNA_lamp_types.h>
58 #include <DNA_material_types.h>
59 #include <DNA_object_types.h>
60 #include <DNA_scene_types.h>
61 #include <DNA_screen_types.h>
62 #include <DNA_scriptlink_types.h>
63 #include <DNA_space_types.h>
64 #include <DNA_text_types.h>
65 #include <DNA_world_types.h>
66 #include <DNA_userdef_types.h> /* for U.pythondir */
68 #include "BPY_extern.h"
69 #include "BPY_menus.h"
70 #include "api2_2x/EXPP_interface.h"
71 #include "api2_2x/constant.h"
73 /* bpy_registryDict is declared in api2_2x/Registry.h and defined
74 * here. This Python dictionary will be used to store data that scripts
75 * choose to preserve after they are executed, so user changes can be
76 * restored next time the script is used. Check the Blender.Registry module. */
77 extern PyObject *bpy_registryDict;
79 /*****************************************************************************/
80 /* Structure definitions */
81 /*****************************************************************************/
82 #define FILENAME_LENGTH 24
83 typedef struct _ScriptError {
84 char filename[FILENAME_LENGTH];
88 /*****************************************************************************/
89 /* Global variables */
90 /*****************************************************************************/
91 ScriptError g_script_error;
92 short EXPP_releaseGlobalDict = 1;
94 /*****************************************************************************/
95 /* Function prototypes */
96 /*****************************************************************************/
97 PyObject *RunPython(Text *text, PyObject *globaldict);
98 char *GetName(Text *text);
99 PyObject *CreateGlobalDictionary (void);
100 void ReleaseGlobalDictionary (PyObject * dict);
101 void DoAllScriptsFromList (ListBase * list, short event);
102 PyObject *importText(char *name);
103 void init_ourImport(void);
104 PyObject *blender_import(PyObject *self, PyObject *args);
106 /*****************************************************************************/
107 /* Description: This function will initialise Python and all the implemented */
108 /* api variations. */
109 /* Notes: Currently only the api for 2.2x will be initialised. */
110 /*****************************************************************************/
111 void BPY_start_python(void)
113 bpy_registryDict = PyDict_New(); /* check comment at start of this file */
115 if (!bpy_registryDict)
116 printf("Error: Couldn't create the Registry Python Dictionary!");
118 /* TODO: Shouldn't "blender" be replaced by PACKAGE ?? (config.h) */
119 Py_SetProgramName("blender");
125 initBlenderApi2_2x ();
132 /*****************************************************************************/
133 /* Description: This function will terminate the Python interpreter */
134 /*****************************************************************************/
135 void BPY_end_python(void)
137 if (bpy_registryDict) {
138 Py_DECREF (bpy_registryDict);
139 bpy_registryDict = NULL;
144 BPyMenu_RemoveAllEntries(); /* freeing bpymenu mem */
149 void syspath_append(char *dirname)
151 PyObject *mod_sys, *dict, *path, *dir;
155 dir = Py_BuildValue("s", dirname);
157 mod_sys = PyImport_ImportModule("sys"); /* new ref */
158 dict = PyModule_GetDict(mod_sys); /* borrowed ref */
159 path = PyDict_GetItemString(dict, "path"); /* borrowed ref */
161 if (!PyList_Check(path)) return;
163 PyList_Append(path, dir);
165 if (PyErr_Occurred()) Py_FatalError("could not build sys.path");
170 void init_syspath(void)
176 char execdir[FILE_MAXDIR + FILE_MAXFILE];/*defines from DNA_space_types.h*/
180 path = Py_BuildValue("s", bprogname);
182 mod = PyImport_ImportModule("Blender.sys");
185 d = PyModule_GetDict(mod);
186 PyDict_SetItemString(d, "progname", path);
190 printf("Warning: could not set Blender.sys.progname\n");
192 progname = BLI_last_slash(bprogname); /* looks for the last dir separator */
194 c = Py_GetPath(); /* get python system path */
195 PySys_SetPath(c); /* initialize */
197 n = progname - bprogname;
199 strncpy(execdir, bprogname, n);
200 if (execdir[n-1] == '.') n--; /*fix for when run as ./blender */
203 syspath_append(execdir); /* append to module search path */
205 /* set Blender.sys.progname */
208 printf ("Warning: could not determine argv[0] path\n");
211 * bring in the site module so we can add
212 * site-package dirs to sys.path
215 mod = PyImport_ImportModule("site"); /* new ref */
222 /* get the value of 'sitedirs' from the module */
224 /* the ref man says GetDict() never fails!!! */
225 d = PyModule_GetDict (mod); /* borrowed ref */
226 p = PyDict_GetItemString (d, "sitedirs"); /* borrowed ref */
228 if( p ) { /* we got our string */
229 /* append each item in sitedirs list to path */
230 size = PyList_Size (p);
232 for (index = 0; index < size; index++) {
233 item = PySequence_GetItem (p, index); /* new ref */
235 syspath_append (PyString_AsString(item));
240 else { /* import 'site' failed */
242 printf("sys_init:warning - no sitedirs added from site module.\n");
246 * initialize the sys module
247 * set sys.executable to the Blender exe
248 * set argv[0] to the Blender exe
251 mod = PyImport_ImportModule("sys"); /* new ref */
254 d = PyModule_GetDict(mod); /* borrowed ref */
255 PyDict_SetItemString(d, "executable", Py_BuildValue("s", bprogname));
256 /* in the future this can be extended to have more argv's if needed: */
257 PyDict_SetItemString(d, "argv", Py_BuildValue("[s]", bprogname));
262 /*****************************************************************************/
263 /* Description: This function finishes Python initialization in Blender. */
264 /* Because U.pythondir (user defined dir for scripts) isn't */
265 /* initialized when BPY_start_Python needs to be executed, we */
266 /* postpone adding U.pythondir to sys.path and also BPyMenus */
267 /* (mechanism to register scripts in Blender menus) for when */
268 /* that dir info is available. */
269 /*****************************************************************************/
270 void BPY_post_start_python(void)
272 if (U.pythondir && U.pythondir[0] != '\0')
273 syspath_append(U.pythondir); /* append to module search path */
275 BPyMenu_Init(0); /* get dynamic menus (registered scripts) data */
278 /*****************************************************************************/
279 /* Description: This function will return the linenumber on which an error */
280 /* has occurred in the Python script. */
281 /*****************************************************************************/
282 int BPY_Err_getLinenumber(void)
284 return g_script_error.lineno;
287 /*****************************************************************************/
288 /* Description: This function will return the filename of the python script. */
289 /*****************************************************************************/
290 const char *BPY_Err_getFilename(void)
292 return g_script_error.filename;
295 /*****************************************************************************/
296 /* Description: Return PyString filename from a traceback object */
297 /*****************************************************************************/
298 PyObject *traceback_getFilename(PyObject *tb)
302 /* co_filename is in f_code, which is in tb_frame, which is in tb */
304 v = PyObject_GetAttrString(tb, "tb_frame"); Py_XDECREF(v);
305 v = PyObject_GetAttrString(v, "f_code"); Py_XDECREF(v);
306 v = PyObject_GetAttrString(v, "co_filename");
311 /*****************************************************************************/
312 /* Description: Blender Python error handler. This catches the error and */
313 /* stores filename and line number in a global */
314 /*****************************************************************************/
315 void BPY_Err_Handle(char *script_name)
317 PyObject *exception, *err, *tb, *v;
320 printf("Error: script has NULL name\n");
324 PyErr_Fetch(&exception, &err, &tb);
326 if (!exception && !tb) {
327 printf("FATAL: spurious exception\n");
331 strcpy(g_script_error.filename, script_name);
333 if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) {
334 /* no traceback available when SyntaxError */
335 PyErr_Restore(exception, err, tb); /* takes away reference! */
337 v = PyObject_GetAttrString(err, "lineno");
338 g_script_error.lineno = PyInt_AsLong(v);
340 /* this avoids an abort in Python 2.3's garbage collecting: */
344 PyErr_NormalizeException(&exception, &err, &tb);
345 PyErr_Restore(exception, err, tb); // takes away reference!
347 tb = PySys_GetObject("last_traceback");
350 printf("\nCan't get traceback\n");
356 /* From old bpython BPY_main.c:
357 * 'check traceback objects and look for last traceback in the
358 * same text file. This is used to jump to the line of where the
359 * error occured. "If the error occured in another text file or module,
360 * the last frame in the current file is adressed."' */
363 v = PyObject_GetAttrString(tb, "tb_next");
365 if (v == Py_None || strcmp(PyString_AsString(traceback_getFilename(v)),
374 v = PyObject_GetAttrString(tb, "tb_lineno");
375 g_script_error.lineno = PyInt_AsLong(v);
377 v = traceback_getFilename(tb);
378 strncpy(g_script_error.filename, PyString_AsString(v), FILENAME_LENGTH);
386 /*****************************************************************************/
387 /* Description: This function executes the script passed by st. */
388 /* Notes: It is called by blender/src/drawtext.c when a Blender user */
389 /* presses ALT+PKEY in the script's text window. */
390 /*****************************************************************************/
391 int BPY_txt_do_python(struct SpaceText* st)
393 PyObject *py_dict, *py_result;
395 Script *script = G.main->script.first;
397 if (!st->text) return 0;
399 /* check if this text is already running */
401 if (!strcmp(script->id.name+2, st->text->id.name+2)) {
402 /* if this text is already a running script, just move to it: */
404 newspace(curarea, SPACE_SCRIPT);
405 sc = curarea->spacedata.first;
409 script = script->id.next;
412 /* Create a new script structure and initialize it: */
413 script = alloc_libblock(&G.main->script, ID_SCRIPT, GetName(st->text));
416 printf("couldn't allocate memory for Script struct!");
421 script->flags = SCRIPT_RUNNING;
422 script->py_draw = NULL;
423 script->py_event = NULL;
424 script->py_button = NULL;
426 py_dict = CreateGlobalDictionary();
428 script->py_globaldict = py_dict;
430 info = (BPy_constant *)M_constant_New();
432 constant_insert(info, "name", PyString_FromString(script->id.name+2));
434 constant_insert(info, "arg", Py_None);
435 PyDict_SetItemString(py_dict, "__script__", (PyObject *)info);
440 py_result = RunPython (st->text, py_dict); /* Run the script */
442 if (!py_result) { /* Failed execution of the script */
444 BPY_Err_Handle(GetName(st->text));
445 ReleaseGlobalDictionary(py_dict);
446 free_libblock(&G.main->script, script);
448 //BPY_start_python();
453 Py_DECREF (py_result);
454 script->flags &=~SCRIPT_RUNNING;
455 if (!script->flags) {
456 ReleaseGlobalDictionary(py_dict);
457 script->py_globaldict = NULL;
458 free_libblock(&G.main->script, script);
462 return 1; /* normal return */
465 /*****************************************************************************/
466 /* Description: This function executes the script chosen from a menu. */
467 /* Notes: It is called by the ui code in src/header_???.c when a user */
468 /* clicks on a menu entry that refers to a script. */
469 /* Scripts are searched in the BPyMenuTable, using the given */
470 /* menutype and event values to know which one was chosen. */
471 /*****************************************************************************/
472 int BPY_menu_do_python(short menutype, int event)
474 PyObject *py_dict, *py_res, *pyarg = NULL;
480 char filestr[FILE_MAXDIR+FILE_MAXFILE];
481 char dirname[FILE_MAXDIR];
482 Script *script = G.main->script.first;
485 pym = BPyMenu_GetEntry(menutype, (short)event);
489 if (pym->version > G.version)
490 notice ("Version mismatch: script was written for Blender %d. "
491 "It may fail with yours: %d.", pym->version, G.version);
493 /* if there are submenus, let the user choose one from a pupmenu that we
495 pysm = pym->submenus;
500 pupstr = BPyMenu_CreatePupmenuStr(pym, menutype);
503 arg = pupmenu(pupstr);
507 while (arg--) pysm = pysm->next;
508 pyarg = PyString_FromString(pysm->arg);
514 if (!pyarg) {/* no submenus */
519 if (pym->dir) /* script is in U.pythondir */
520 BLI_make_file_string("/", filestr, U.pythondir, pym->filename);
521 else { /* script is in ~/.blender/scripts/ */
522 BLI_make_file_string("/", dirname, bpymenu_gethome(), "scripts");
523 BLI_make_file_string("/", filestr, dirname, pym->filename);
526 fp = fopen(filestr, "r");
527 if (!fp) { /* later also support userhome/.blender/scripts/ or whatever */
528 printf("Error loading script: couldn't open file %s\n", filestr);
532 /* Create a new script structure and initialize it: */
533 script = alloc_libblock(&G.main->script, ID_SCRIPT, pym->name);
536 printf("couldn't allocate memory for Script struct!");
542 script->flags = SCRIPT_RUNNING;
543 script->py_draw = NULL;
544 script->py_event = NULL;
545 script->py_button = NULL;
547 py_dict = CreateGlobalDictionary();
549 script->py_globaldict = py_dict;
551 info = (BPy_constant *)M_constant_New();
553 constant_insert(info, "name", PyString_FromString(script->id.name+2));
554 constant_insert(info, "arg", pyarg);
555 PyDict_SetItemString(py_dict, "__script__", (PyObject *)info);
560 /* Previously we used PyRun_File to run directly the code on a FILE object,
561 * but as written in the Python/C API Ref Manual, chapter 2,
562 * 'FILE structs for different C libraries can be different and incompatible'
564 * So now we load the script file data to a buffer */
566 fseek(fp, 0L, SEEK_END);
568 fseek(fp, 0L, SEEK_SET);
570 buffer = MEM_mallocN(len+1, "pyfilebuf"); /* len+1 to add '\0' */
571 len = fread(buffer, 1, len, fp);
577 /* run the string buffer */
579 py_res = PyRun_String(buffer, Py_file_input, py_dict, py_dict);
583 if (!py_res) { /* Failed execution of the script */
585 BPY_Err_Handle(script->id.name+2);
587 ReleaseGlobalDictionary(py_dict);
588 free_libblock(&G.main->script, script);
590 // BPY_start_python();
591 error ("Python script error: check console");
597 script->flags &=~SCRIPT_RUNNING;
598 if (!script->flags) {
599 ReleaseGlobalDictionary(py_dict);
600 script->py_globaldict = NULL;
601 free_libblock(&G.main->script, script);
605 return 1; /* normal return */
608 /*****************************************************************************/
611 /*****************************************************************************/
612 void BPY_free_compiled_text(struct Text* text)
614 if (!text->compiled) return;
615 Py_DECREF((PyObject*) text->compiled);
616 text->compiled = NULL;
621 /*****************************************************************************/
622 /* Description: This function frees a finished (flags == 0) script. */
623 /*****************************************************************************/
624 void BPY_free_finished_script(Script *script)
628 free_libblock(&G.main->script, script);
632 void unlink_script(Script *script)
633 { /* copied from unlink_text in drawtext.c */
638 for (scr= G.main->screen.first; scr; scr= scr->id.next) {
639 for (area= scr->areabase.first; area; area= area->next) {
640 for (sl= area->spacedata.first; sl; sl= sl->next) {
641 if (sl->spacetype==SPACE_SCRIPT) {
642 SpaceScript *sc= (SpaceScript*) sl;
644 if (sc->script==script) {
647 if (sc==area->spacedata.first) {
648 scrarea_queue_redraw(area);
657 void BPY_clear_script (Script *script)
663 Py_XDECREF((PyObject *)script->py_draw);
664 Py_XDECREF((PyObject *)script->py_event);
665 Py_XDECREF((PyObject *)script->py_button);
667 dict = script->py_globaldict;
671 Py_DECREF (dict); /* Release dictionary. */
672 script->py_globaldict = NULL;
675 unlink_script (script);
678 /*****************************************************************************/
680 /*****************************************************************************/
682 /*****************************************************************************/
684 /* Notes: Not implemented yet */
685 /*****************************************************************************/
686 void BPY_clear_bad_scriptlinks(struct Text *byebye)
689 BPY_clear_bad_scriptlist(getObjectList(), byebye);
690 BPY_clear_bad_scriptlist(getLampList(), byebye);
691 BPY_clear_bad_scriptlist(getCameraList(), byebye);
692 BPY_clear_bad_scriptlist(getMaterialList(), byebye);
693 BPY_clear_bad_scriptlist(getWorldList(), byebye);
694 BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye);
696 allqueue(REDRAWBUTSSCRIPT, 0);
701 /*****************************************************************************/
702 /* Description: Loop through all scripts of a list of object types, and */
703 /* execute these scripts. */
704 /* For the scene, only the current active scene the scripts are */
705 /* executed (if any). */
706 /*****************************************************************************/
707 void BPY_do_all_scripts(short event)
709 DoAllScriptsFromList (&(G.main->object), event);
710 DoAllScriptsFromList (&(G.main->lamp), event);
711 DoAllScriptsFromList (&(G.main->camera), event);
712 DoAllScriptsFromList (&(G.main->mat), event);
713 DoAllScriptsFromList (&(G.main->world), event);
715 BPY_do_pyscript (&(G.scene->id), event);
720 /*****************************************************************************/
721 /* Description: Execute a Python script when an event occurs. The following */
722 /* events are possible: frame changed, load script and redraw. */
723 /* Only events happening to one of the following object types */
724 /* are handled: Object, Lamp, Camera, Material, World and */
726 /*****************************************************************************/
727 void BPY_do_pyscript(struct ID *id, short event)
729 ScriptLink * scriptlink;
734 scriptlink = setScriptLinks (id, event);
736 if (scriptlink == NULL) return;
738 for (index = 0; index < scriptlink->totscript; index++)
740 if ((scriptlink->flag[index] == event) &&
741 (scriptlink->scripts[index] != NULL))
743 dict = CreateGlobalDictionary();
744 ret = RunPython ((Text*) scriptlink->scripts[index], dict);
745 ReleaseGlobalDictionary (dict);
748 /* Failed execution of the script */
749 BPY_Err_Handle (scriptlink->scripts[index]->name+2);
763 /*****************************************************************************/
766 /*****************************************************************************/
767 void BPY_free_scriptlink(struct ScriptLink *slink)
769 if (slink->totscript) {
770 if(slink->flag) MEM_freeN(slink->flag);
771 if(slink->scripts) MEM_freeN(slink->scripts);
777 /*****************************************************************************/
780 /*****************************************************************************/
781 void BPY_copy_scriptlink(struct ScriptLink *scriptlink)
785 if (scriptlink->totscript) {
787 tmp = scriptlink->scripts;
788 scriptlink->scripts =
789 MEM_mallocN(sizeof(ID*)*scriptlink->totscript, "scriptlistL");
790 memcpy(scriptlink->scripts, tmp, sizeof(ID*)*scriptlink->totscript);
792 tmp = scriptlink->flag;
794 MEM_mallocN(sizeof(short)*scriptlink->totscript, "scriptlistF");
795 memcpy(scriptlink->flag, tmp, sizeof(short)*scriptlink->totscript);
801 /*****************************************************************************/
803 /* Notes: Not implemented yet */
804 /*****************************************************************************/
805 int BPY_call_importloader(char *name)
806 { /* XXX Should this function go away from Blender? */
807 printf ("In BPY_call_importloader(name=%s)\n",name);
811 /*****************************************************************************/
812 /* Private functions */
813 /*****************************************************************************/
815 /*****************************************************************************/
816 /* Description: This function executes the python script passed by text. */
817 /* The Python dictionary containing global variables needs to */
818 /* be passed in globaldict. */
819 /*****************************************************************************/
820 PyObject * RunPython(Text *text, PyObject *globaldict)
824 /* The script text is compiled to Python bytecode and saved at text->compiled
825 * to speed-up execution if the user executes the script multiple times */
827 if (!text->compiled) { /* if it wasn't already compiled, do it now */
828 buf = txt_to_buf(text);
830 text->compiled = Py_CompileString(buf, GetName(text), Py_file_input);
834 if (PyErr_Occurred()) {
835 BPY_free_compiled_text(text);
841 return PyEval_EvalCode(text->compiled, globaldict, globaldict);
844 /*****************************************************************************/
845 /* Description: This function returns the value of the name field of the */
846 /* given Text struct. */
847 /*****************************************************************************/
848 char * GetName(Text *text)
850 return (text->id.name+2);
853 /*****************************************************************************/
854 /* Description: This function creates a new Python dictionary object. */
855 /*****************************************************************************/
856 PyObject * CreateGlobalDictionary (void)
858 PyObject *dict = PyDict_New();
860 PyDict_SetItemString (dict, "__builtins__", PyEval_GetBuiltins());
861 PyDict_SetItemString (dict, "__name__", PyString_FromString("__main__"));
866 /*****************************************************************************/
867 /* Description: This function deletes a given Python dictionary object. */
868 /*****************************************************************************/
869 void ReleaseGlobalDictionary (PyObject * dict)
872 Py_DECREF (dict); /* Release dictionary. */
877 /*****************************************************************************/
878 /* Description: This function runs all scripts (if any) present in the */
879 /* list argument. The event by which the function has been */
880 /* called, is passed in the event argument. */
881 /*****************************************************************************/
882 void DoAllScriptsFromList (ListBase *list, short event)
889 BPY_do_pyscript (id, event);
896 PyObject *importText(char *name)
901 int namelen = strlen(name);
903 txtname = malloc(namelen+3+1);
904 if (!txtname) return NULL;
906 memcpy(txtname, name, namelen);
907 memcpy(&txtname[namelen], ".py", 4);
909 text = (Text*) &(G.main->text.first);
912 if (!strcmp (txtname, GetName(text)))
914 text = text->id.next;
922 if (!text->compiled) {
923 buf = txt_to_buf(text);
924 text->compiled = Py_CompileString(buf, GetName(text), Py_file_input);
927 if (PyErr_Occurred()) {
929 BPY_free_compiled_text(text);
936 return PyImport_ExecCodeModule(name, text->compiled);
939 static PyMethodDef bimport[] = {
940 { "blimport", blender_import, METH_VARARGS, "our own import"}
943 PyObject *blender_import(PyObject *self, PyObject *args)
945 PyObject *exception, *err, *tb;
947 PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
950 if (!PyArg_ParseTuple(args, "s|OOO:bimport",
951 &name, &globals, &locals, &fromlist))
954 m = PyImport_ImportModuleEx(name, globals, locals, fromlist);
959 PyErr_Fetch(&exception, &err, &tb); /*restore for probable later use*/
961 m = importText(name);
962 if (m) { /* found module, ignore above exception*/
964 Py_XDECREF(exception); Py_XDECREF(err); Py_XDECREF(tb);
965 printf("imported from text buffer...\n");
967 PyErr_Restore(exception, err, tb);
972 void init_ourImport(void)
975 PyObject *import = PyCFunction_New(bimport, NULL);
977 m = PyImport_AddModule("__builtin__");
978 d = PyModule_GetDict(m);
979 PyDict_SetItemString(d, "__import__", import);