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>
43 #include <BLI_blenlib.h> /* for BLI_last_slash() */
45 #include <BKE_global.h>
48 #include <DNA_camera_types.h>
50 #include <DNA_lamp_types.h>
51 #include <DNA_material_types.h>
52 #include <DNA_object_types.h>
53 #include <DNA_scene_types.h>
54 #include <DNA_scriptlink_types.h>
55 #include <DNA_space_types.h>
56 #include <DNA_text_types.h>
57 #include <DNA_world_types.h>
59 #include <DNA_userdef_types.h> /* for U.pythondir */
61 #include "BPY_extern.h"
62 #include "api2_2x/EXPP_interface.h"
64 /* bpy_registryDict is declared in api2_2x/Registry.h and defined
65 * here. This Python dictionary will be used to store data that scripts
66 * choose to preserve after they are executed, so user changes can be
67 * restored next time the script is used. Check the Blender.Registry module. */
68 extern PyObject *bpy_registryDict;
70 /*****************************************************************************/
71 /* Structure definitions */
72 /*****************************************************************************/
73 #define FILENAME_LENGTH 24
74 typedef struct _ScriptError {
75 char filename[FILENAME_LENGTH];
79 /*****************************************************************************/
80 /* Global variables */
81 /*****************************************************************************/
82 ScriptError g_script_error;
83 short EXPP_releaseGlobalDict = 1;
85 /*****************************************************************************/
86 /* Function prototypes */
87 /*****************************************************************************/
88 PyObject *RunPython(Text *text, PyObject *globaldict);
89 char *GetName(Text *text);
90 PyObject *CreateGlobalDictionary (void);
91 void ReleaseGlobalDictionary (PyObject * dict);
92 void DoAllScriptsFromList (ListBase * list, short event);
93 PyObject *importText(char *name);
94 void init_ourImport(void);
95 PyObject *blender_import(PyObject *self, PyObject *args);
97 /*****************************************************************************/
98 /* Description: This function will initialise Python and all the implemented */
100 /* Notes: Currently only the api for 2.2x will be initialised. */
101 /*****************************************************************************/
102 void BPY_start_python(void)
104 bpy_registryDict = PyDict_New(); /* check comment at start of this file */
106 if (!bpy_registryDict)
107 printf("Error: Couldn't create the Registry Python Dictionary!");
109 /* TODO: Shouldn't "blender" be replaced by PACKAGE ?? (config.h) */
110 Py_SetProgramName("blender");
116 initBlenderApi2_2x ();
123 /*****************************************************************************/
124 /* Description: This function will terminate the Python interpreter */
125 /*****************************************************************************/
126 void BPY_end_python(void)
128 if (bpy_registryDict) {
129 Py_DECREF (bpy_registryDict);
130 bpy_registryDict = NULL;
137 void syspath_append(PyObject *dir)
139 PyObject *mod_sys, *dict, *path;
143 mod_sys = PyImport_ImportModule("sys"); /* new ref */
144 dict = PyModule_GetDict(mod_sys); /* borrowed ref */
145 path = PyDict_GetItemString(dict, "path"); /* borrowed ref */
147 if (!PyList_Check(path)) return;
149 PyList_Append(path, dir);
151 if (PyErr_Occurred()) Py_FatalError("could not build sys.path");
156 void init_syspath(void)
162 char execdir[FILE_MAXDIR + FILE_MAXFILE];/*defines from DNA_space_types.h*/
166 path = Py_BuildValue("s", bprogname);
168 mod = PyImport_ImportModule("Blender.sys");
171 d = PyModule_GetDict(mod);
172 PyDict_SetItemString(d, "progname", path);
176 printf("Warning: could not set Blender.sys.progname\n");
178 progname = BLI_last_slash(bprogname); /* looks for the last dir separator */
180 c = Py_GetPath(); /* get python system path */
181 PySys_SetPath(c); /* initialize */
183 n = progname - bprogname;
185 strncpy(execdir, bprogname, n);
186 if (execdir[n-1] == '.') n--; /*fix for when run as ./blender */
189 p = Py_BuildValue("s", execdir);
190 syspath_append(p); /* append to module search path */
192 /* set Blender.sys.progname */
195 printf ("Warning: could not determine argv[0] path\n");
198 p = Py_BuildValue("s", U.pythondir);
199 syspath_append(p); /* append to module search path */
203 * bring in the site module so we can add
204 * site-package dirs to sys.path
207 mod = PyImport_ImportModule("site"); /* new ref */
214 /* get the value of 'sitedirs' from the module */
216 /* the ref man says GetDict() never fails!!! */
217 d = PyModule_GetDict (mod); /* borrowed ref */
218 p = PyDict_GetItemString (d, "sitedirs"); /* borrowed ref */
220 if( p ) { /* we got our string */
221 /* append each item in sitedirs list to path */
222 size = PyList_Size (p);
224 for (index = 0; index < size; index++) {
225 item = PySequence_GetItem (p, index); /* new ref */
227 syspath_append (item);
232 else { /* import 'site' failed */
234 printf("sys_init:warning - no sitedirs added from site module.\n");
238 * initialize the sys module
239 * set sys.executable to the Blender exe
240 * set argv[0] to the Blender exe
243 mod = PyImport_ImportModule("sys"); /* new ref */
246 d = PyModule_GetDict(mod); /* borrowed ref */
247 PyDict_SetItemString(d, "executable", Py_BuildValue("s", bprogname));
248 /* in the future this can be extended to have more argv's if needed: */
249 PyDict_SetItemString(d, "argv", Py_BuildValue("[s]", bprogname));
254 /*****************************************************************************/
255 /* Description: This function adds the user defined folder for Python */
256 /* scripts to sys.path. This is done in init_syspath, too, but */
257 /* when Blender's main() runs BPY_start_python(), U.pythondir */
258 /* isn't set yet, so we provide this function to be executed */
259 /* after U.pythondir is defined. */
260 /*****************************************************************************/
261 void BPY_syspath_append_pythondir(void)
263 syspath_append(Py_BuildValue("s", U.pythondir));
266 /*****************************************************************************/
267 /* Description: This function will return the linenumber on which an error */
268 /* has occurred in the Python script. */
269 /*****************************************************************************/
270 int BPY_Err_getLinenumber(void)
272 return g_script_error.lineno;
275 /*****************************************************************************/
276 /* Description: This function will return the filename of the python script. */
277 /*****************************************************************************/
278 const char *BPY_Err_getFilename(void)
280 return g_script_error.filename;
283 /*****************************************************************************/
284 /* Description: Return PyString filename from a traceback object */
285 /*****************************************************************************/
286 PyObject *traceback_getFilename(PyObject *tb)
290 /* co_filename is in f_code, which is in tb_frame, which is in tb */
292 v = PyObject_GetAttrString(tb, "tb_frame"); Py_XDECREF(v);
293 v = PyObject_GetAttrString(v, "f_code"); Py_XDECREF(v);
294 v = PyObject_GetAttrString(v, "co_filename");
299 /*****************************************************************************/
300 /* Description: Blender Python error handler. This catches the error and */
301 /* stores filename and line number in a global */
302 /*****************************************************************************/
303 void BPY_Err_Handle(Text *text)
305 PyObject *exception, *err, *tb, *v;
307 PyErr_Fetch(&exception, &err, &tb);
309 if (!exception && !tb) {
310 printf("FATAL: spurious exception\n");
314 strcpy(g_script_error.filename, GetName(text));
316 if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) {
317 /* no traceback available when SyntaxError */
318 PyErr_Restore(exception, err, tb); /* takes away reference! */
320 v = PyObject_GetAttrString(err, "lineno");
321 g_script_error.lineno = PyInt_AsLong(v);
323 /* this avoids an abort in Python 2.3's garbage collecting: */
327 PyErr_NormalizeException(&exception, &err, &tb);
328 PyErr_Restore(exception, err, tb); // takes away reference!
330 tb = PySys_GetObject("last_traceback");
333 printf("\nCan't get traceback\n");
339 /* From old bpython BPY_main.c:
340 * 'check traceback objects and look for last traceback in the
341 * same text file. This is used to jump to the line of where the
342 * error occured. "If the error occured in another text file or module,
343 * the last frame in the current file is adressed."' */
346 v = PyObject_GetAttrString(tb, "tb_next");
348 if (v == Py_None || strcmp(PyString_AsString(traceback_getFilename(v)),
357 v = PyObject_GetAttrString(tb, "tb_lineno");
358 g_script_error.lineno = PyInt_AsLong(v);
360 v = traceback_getFilename(tb);
361 strncpy(g_script_error.filename, PyString_AsString(v), FILENAME_LENGTH);
369 /*****************************************************************************/
370 /* Description: This function executes the script passed by st. */
371 /* Notes: It is called by blender/src/drawtext.c when a Blender user */
372 /* presses ALT+PKEY in the script's text window. */
373 /*****************************************************************************/
374 struct _object *BPY_txt_do_python(struct SpaceText* st)
376 PyObject *dict, *ret;
377 PyObject *main_dict = PyModule_GetDict(PyImport_AddModule("__main__"));
379 if (!st->text) return NULL;
381 /* The EXPP_releaseGlobalDict global variable controls whether we should run
382 * the script with a clean global dictionary or should keep the current one,
383 * possibly already "polluted" by other calls to the Python Interpreter.
384 * The default is to use a clean one. To change this the script writer must
385 * call Blender.ReleaseGlobalDict(bool), with bool == 0, in the script. */
387 if (EXPP_releaseGlobalDict) {
388 printf("Using a clean Global Dictionary.\n");
389 st->flags |= ST_CLEAR_NAMESPACE;
390 dict = CreateGlobalDictionary();
393 dict = main_dict; /* must be careful not to free the main_dict */
397 ret = RunPython (st->text, dict); /* Run the script */
399 if (!ret) { /* Failed execution of the script */
401 if (EXPP_releaseGlobalDict && (dict != main_dict))
402 ReleaseGlobalDictionary(dict);
404 BPY_Err_Handle(st->text);
411 else Py_DECREF (ret);
413 /* Scripts that use the GUI rely on the persistent global namespace, so
414 * they need a workaround: The namespace is released when the GUI is exit.'
415 * See api2_2x/Draw.c: Method_Register() */
417 /* Block below: The global dict should only be released if:
418 * - a script didn't defined it to be persistent and
419 * - Draw.Register() is not in use (no GUI) and
420 * - it is not the real __main__ dict (if it is, restart to clean it) */
422 if (EXPP_releaseGlobalDict) {
423 if (st->flags & ST_CLEAR_NAMESPACE) { /* False if the GUI is in use */
425 if (dict != main_dict) ReleaseGlobalDictionary(dict);
428 BPY_end_python(); /* restart to get a fresh __main__ dict */
434 else if (dict != main_dict) PyDict_Update (main_dict, dict);
436 /* Line above: if it should be kept and it's not already the __main__ dict,
437 * merge it into the __main__ one. This happens when to release is the
438 * current behavior and the script changes that with
439 * Blender.ReleaseGlobalDict(0). */
441 /* Edited from old BPY_main.c:
442 * 'The return value is the global namespace dictionary of the script
443 * context. This may be stored in the SpaceText instance to give control
444 * over namespace persistence. Remember that the same script may be
445 * executed in several windows ... Namespace persistence is desired for
446 * scripts that use the GUI and store callbacks to the current script.' */
451 /*****************************************************************************/
454 /*****************************************************************************/
455 void BPY_free_compiled_text(struct Text* text)
457 if (!text->compiled) return;
458 Py_DECREF((PyObject*) text->compiled);
459 text->compiled = NULL;
464 /*****************************************************************************/
466 /*****************************************************************************/
468 /*****************************************************************************/
470 /* Notes: Not implemented yet */
471 /*****************************************************************************/
472 void BPY_clear_bad_scriptlinks(struct Text *byebye)
475 BPY_clear_bad_scriptlist(getObjectList(), byebye);
476 BPY_clear_bad_scriptlist(getLampList(), byebye);
477 BPY_clear_bad_scriptlist(getCameraList(), byebye);
478 BPY_clear_bad_scriptlist(getMaterialList(), byebye);
479 BPY_clear_bad_scriptlist(getWorldList(), byebye);
480 BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye);
482 allqueue(REDRAWBUTSSCRIPT, 0);
487 /*****************************************************************************/
488 /* Description: Loop through all scripts of a list of object types, and */
489 /* execute these scripts. */
490 /* For the scene, only the current active scene the scripts are */
491 /* executed (if any). */
492 /*****************************************************************************/
493 void BPY_do_all_scripts(short event)
495 DoAllScriptsFromList (&(G.main->object), event);
496 DoAllScriptsFromList (&(G.main->lamp), event);
497 DoAllScriptsFromList (&(G.main->camera), event);
498 DoAllScriptsFromList (&(G.main->mat), event);
499 DoAllScriptsFromList (&(G.main->world), event);
501 BPY_do_pyscript (&(G.scene->id), event);
506 /*****************************************************************************/
507 /* Description: Execute a Python script when an event occurs. The following */
508 /* events are possible: frame changed, load script and redraw. */
509 /* Only events happening to one of the following object types */
510 /* are handled: Object, Lamp, Camera, Material, World and */
512 /*****************************************************************************/
513 void BPY_do_pyscript(struct ID *id, short event)
515 ScriptLink * scriptlink;
520 scriptlink = setScriptLinks (id, event);
522 if (scriptlink == NULL) return;
524 for (index = 0; index < scriptlink->totscript; index++)
526 if ((scriptlink->flag[index] == event) &&
527 (scriptlink->scripts[index] != NULL))
529 dict = CreateGlobalDictionary();
530 ret = RunPython ((Text*) scriptlink->scripts[index], dict);
531 ReleaseGlobalDictionary (dict);
534 /* Failed execution of the script */
535 BPY_Err_Handle ((Text*) scriptlink->scripts[index]);
549 /*****************************************************************************/
552 /*****************************************************************************/
553 void BPY_free_scriptlink(struct ScriptLink *slink)
555 if (slink->totscript) {
556 if(slink->flag) MEM_freeN(slink->flag);
557 if(slink->scripts) MEM_freeN(slink->scripts);
563 /*****************************************************************************/
566 /*****************************************************************************/
567 void BPY_copy_scriptlink(struct ScriptLink *scriptlink)
571 if (scriptlink->totscript) {
573 tmp = scriptlink->scripts;
574 scriptlink->scripts =
575 MEM_mallocN(sizeof(ID*)*scriptlink->totscript, "scriptlistL");
576 memcpy(scriptlink->scripts, tmp, sizeof(ID*)*scriptlink->totscript);
578 tmp = scriptlink->flag;
580 MEM_mallocN(sizeof(short)*scriptlink->totscript, "scriptlistF");
581 memcpy(scriptlink->flag, tmp, sizeof(short)*scriptlink->totscript);
587 /*****************************************************************************/
589 /* Notes: Not implemented yet */
590 /*****************************************************************************/
591 int BPY_call_importloader(char *name)
592 { /* XXX Should this function go away from Blender? */
593 printf ("In BPY_call_importloader(name=%s)\n",name);
597 /*****************************************************************************/
598 /* Private functions */
599 /*****************************************************************************/
601 /*****************************************************************************/
602 /* Description: This function executes the python script passed by text. */
603 /* The Python dictionary containing global variables needs to */
604 /* be passed in globaldict. */
605 /*****************************************************************************/
606 PyObject * RunPython(Text *text, PyObject *globaldict)
610 /* The script text is compiled to Python bytecode and saved at text->compiled
611 * to speed-up execution if the user executes the script multiple times */
613 if (!text->compiled) { /* if it wasn't already compiled, do it now */
614 buf = txt_to_buf(text);
616 text->compiled = Py_CompileString(buf, GetName(text), Py_file_input);
620 if (PyErr_Occurred()) {
621 BPY_free_compiled_text(text);
627 return PyEval_EvalCode(text->compiled, globaldict, globaldict);
630 /*****************************************************************************/
631 /* Description: This function returns the value of the name field of the */
632 /* given Text struct. */
633 /*****************************************************************************/
634 char * GetName(Text *text)
636 return (text->id.name+2);
639 /*****************************************************************************/
640 /* Description: This function creates a new Python dictionary object. */
641 /*****************************************************************************/
642 PyObject * CreateGlobalDictionary (void)
644 PyObject *dict = PyDict_New();
646 PyDict_SetItemString (dict, "__builtins__", PyEval_GetBuiltins());
647 PyDict_SetItemString (dict, "__name__", PyString_FromString("__main__"));
652 /*****************************************************************************/
653 /* Description: This function deletes a given Python dictionary object. */
654 /*****************************************************************************/
655 void ReleaseGlobalDictionary (PyObject * dict)
658 Py_DECREF (dict); /* Release dictionary. */
663 /*****************************************************************************/
664 /* Description: This function runs all scripts (if any) present in the */
665 /* list argument. The event by which the function has been */
666 /* called, is passed in the event argument. */
667 /*****************************************************************************/
668 void DoAllScriptsFromList (ListBase *list, short event)
675 BPY_do_pyscript (id, event);
682 PyObject *importText(char *name)
687 int namelen = strlen(name);
689 txtname = malloc(namelen+3+1);
690 if (!txtname) return NULL;
692 memcpy(txtname, name, namelen);
693 memcpy(&txtname[namelen], ".py", 4);
695 text = (Text*) &(G.main->text.first);
698 if (!strcmp (txtname, GetName(text)))
700 text = text->id.next;
708 if (!text->compiled) {
709 buf = txt_to_buf(text);
710 text->compiled = Py_CompileString(buf, GetName(text), Py_file_input);
713 if (PyErr_Occurred()) {
715 BPY_free_compiled_text(text);
722 return PyImport_ExecCodeModule(name, text->compiled);
725 static PyMethodDef bimport[] = {
726 { "blimport", blender_import, METH_VARARGS, "our own import"}
729 PyObject *blender_import(PyObject *self, PyObject *args)
731 PyObject *exception, *err, *tb;
733 PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
736 if (!PyArg_ParseTuple(args, "s|OOO:bimport",
737 &name, &globals, &locals, &fromlist))
740 m = PyImport_ImportModuleEx(name, globals, locals, fromlist);
745 PyErr_Fetch(&exception, &err, &tb); /*restore for probable later use*/
747 m = importText(name);
748 if (m) { /* found module, ignore above exception*/
750 Py_XDECREF(exception); Py_XDECREF(err); Py_XDECREF(tb);
751 printf("imported from text buffer...\n");
753 PyErr_Restore(exception, err, tb);
758 void init_ourImport(void)
761 PyObject *import = PyCFunction_New(bimport, NULL);
763 m = PyImport_AddModule("__builtin__");
764 d = PyModule_GetDict(m);
765 PyDict_SetItemString(d, "__import__", import);