| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 20:10:08 +00:00
										 |  |  | /** \file blender/python/intern/bpy_traceback.c
 | 
					
						
							|  |  |  |  *  \ingroup pythonintern | 
					
						
							| 
									
										
										
										
											2011-11-05 08:21:12 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This file contains utility functions for getting data from a python stack | 
					
						
							|  |  |  |  * trace. | 
					
						
							| 
									
										
										
										
											2011-02-27 20:10:08 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | #include <Python.h>
 | 
					
						
							|  |  |  | #include <frameobject.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 18:36:37 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-08 02:19:41 +00:00
										 |  |  | #include "BLI_path_util.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-01 07:21:08 +10:00
										 |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  | #  include "BLI_string.h"  /* BLI_strcasecmp */
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-03-08 02:19:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | #include "bpy_traceback.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-26 17:55:03 +00:00
										 |  |  | static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 	return PyBytes_AS_STRING((*coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | /* copied from pythonrun.c, 3.4.0 */ | 
					
						
							|  |  |  | _Py_static_string(PyId_string, "<string>"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename, | 
					
						
							|  |  |  |                    int *lineno, int *offset, PyObject **text) | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 	long hold; | 
					
						
							|  |  |  | 	PyObject *v; | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	_Py_IDENTIFIER(msg); | 
					
						
							|  |  |  | 	_Py_IDENTIFIER(filename); | 
					
						
							|  |  |  | 	_Py_IDENTIFIER(lineno); | 
					
						
							|  |  |  | 	_Py_IDENTIFIER(offset); | 
					
						
							|  |  |  | 	_Py_IDENTIFIER(text); | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	*message = NULL; | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | 	*filename = NULL; | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* new style errors.  `err' is an instance */ | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	*message = _PyObject_GetAttrId(err, &PyId_msg); | 
					
						
							|  |  |  | 	if (!*message) | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 		goto finally; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	v = _PyObject_GetAttrId(err, &PyId_filename); | 
					
						
							|  |  |  | 	if (!v) | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 		goto finally; | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	if (v == Py_None) { | 
					
						
							|  |  |  | 		Py_DECREF(v); | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | 		*filename = _PyUnicode_FromId(&PyId_string); | 
					
						
							|  |  |  | 		if (*filename == NULL) | 
					
						
							|  |  |  | 			goto finally; | 
					
						
							|  |  |  | 		Py_INCREF(*filename); | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | 		*filename = v; | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	v = _PyObject_GetAttrId(err, &PyId_lineno); | 
					
						
							|  |  |  | 	if (!v) | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 		goto finally; | 
					
						
							|  |  |  | 	hold = PyLong_AsLong(v); | 
					
						
							|  |  |  | 	Py_DECREF(v); | 
					
						
							|  |  |  | 	if (hold < 0 && PyErr_Occurred()) | 
					
						
							|  |  |  | 		goto finally; | 
					
						
							|  |  |  | 	*lineno = (int)hold; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	v = _PyObject_GetAttrId(err, &PyId_offset); | 
					
						
							|  |  |  | 	if (!v) | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 		goto finally; | 
					
						
							|  |  |  | 	if (v == Py_None) { | 
					
						
							|  |  |  | 		*offset = -1; | 
					
						
							|  |  |  | 		Py_DECREF(v); | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 		hold = PyLong_AsLong(v); | 
					
						
							|  |  |  | 		Py_DECREF(v); | 
					
						
							|  |  |  | 		if (hold < 0 && PyErr_Occurred()) | 
					
						
							|  |  |  | 			goto finally; | 
					
						
							|  |  |  | 		*offset = (int)hold; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	v = _PyObject_GetAttrId(err, &PyId_text); | 
					
						
							|  |  |  | 	if (!v) | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 		goto finally; | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	if (v == Py_None) { | 
					
						
							|  |  |  | 		Py_DECREF(v); | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 		*text = NULL; | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | 		*text = v; | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | finally: | 
					
						
							| 
									
										
										
										
											2012-12-04 20:09:07 +00:00
										 |  |  | 	Py_XDECREF(*message); | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | 	Py_XDECREF(*filename); | 
					
						
							| 
									
										
										
										
											2011-04-21 13:11:51 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | /* end copied function! */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void python_script_error_jump(const char *filepath, int *lineno, int *offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *exception, *value; | 
					
						
							|  |  |  | 	PyTracebackObject *tb; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 	*lineno = -1; | 
					
						
							|  |  |  | 	*offset = 0; | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_Fetch(&exception, &value, (PyObject **)&tb); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 	if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 		/* no traceback available when SyntaxError.
 | 
					
						
							|  |  |  | 		 * python has no api's to this. reference parse_syntax_error() from pythonrun.c */ | 
					
						
							|  |  |  | 		PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); | 
					
						
							| 
									
										
										
										
											2012-03-26 20:41:54 +00:00
										 |  |  | 		PyErr_Restore(exception, value, (PyObject *)tb);  /* takes away reference! */ | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 		if (value) { /* should always be true */ | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 			PyObject *message; | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | 			PyObject *filename_py, *text_py; | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 06:24:29 +10:00
										 |  |  | 			if (parse_syntax_error(value, &message, &filename_py, lineno, offset, &text_py)) { | 
					
						
							|  |  |  | 				const char *filename = _PyUnicode_AsString(filename_py); | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 				/* python adds a '/', prefix, so check for both */ | 
					
						
							| 
									
										
										
										
											2012-03-08 02:19:41 +00:00
										 |  |  | 				if ((BLI_path_cmp(filename, filepath) == 0) || | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 				    ((filename[0] == '\\' || filename[0] == '/') && BLI_path_cmp(filename + 1, filepath) == 0)) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 					/* good */ | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 					*lineno = -1; | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 				*lineno = -1; | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); | 
					
						
							| 
									
										
										
										
											2012-03-26 20:41:54 +00:00
										 |  |  | 		PyErr_Restore(exception, value, (PyObject *)tb);  /* takes away reference! */ | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 		PyErr_Print(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 		for (tb = (PyTracebackObject *)PySys_GetObject("last_traceback"); | 
					
						
							| 
									
										
										
										
											2011-11-26 15:18:30 +00:00
										 |  |  | 		     tb && (PyObject *)tb != Py_None; | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 		     tb = tb->tb_next) | 
					
						
							| 
									
										
										
										
											2011-11-26 15:18:30 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-08-26 17:55:03 +00:00
										 |  |  | 			PyObject *coerce; | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 			const char *tb_filepath = traceback_filepath(tb, &coerce); | 
					
						
							| 
									
										
										
										
											2012-03-30 05:26:08 +00:00
										 |  |  | 			const int match = ((BLI_path_cmp(tb_filepath, filepath) == 0) || | 
					
						
							|  |  |  | 			                   ((tb_filepath[0] == '\\' || tb_filepath[0] == '/') && BLI_path_cmp(tb_filepath + 1, filepath) == 0)); | 
					
						
							| 
									
										
										
										
											2011-08-26 17:55:03 +00:00
										 |  |  | 			Py_DECREF(coerce); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 			if (match) { | 
					
						
							| 
									
										
										
										
											2011-12-26 12:26:11 +00:00
										 |  |  | 				*lineno = tb->tb_lineno; | 
					
						
							| 
									
										
										
										
											2012-03-30 05:26:08 +00:00
										 |  |  | 				/* used to break here, but better find the inner most line */ | 
					
						
							| 
									
										
										
										
											2011-02-22 11:32:29 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |