// Copyright (c) Corporation for National Research Initiatives package org.python.core; import org.python.core.util.RelativeFile; import org.python.expose.ExposedGet; import org.python.expose.ExposedType; /** * A python traceback object. */ @ExposedType(name = "traceback", isBaseType = false) public class PyTraceback extends PyObject { public static final PyType TYPE = PyType.fromClass(PyTraceback.class); @ExposedGet public PyObject tb_next; @ExposedGet public PyFrame tb_frame; @ExposedGet public int tb_lineno; public PyTraceback(PyTraceback next, PyFrame frame) { super(TYPE); tb_next = next; tb_frame = frame; tb_lineno = frame.f_code.getline(frame); } private String tracebackInfo() { if (tb_frame == null || tb_frame.f_code == null) { return String.format(" (no code object) at line %s\n", tb_lineno); } String line = null; if (tb_frame.f_code.co_filename != null) { line = getLine(tb_frame.f_code.co_filename, tb_lineno); } return String.format(" File \"%.500s\", line %d, in %.500s\n%s", tb_frame.f_code.co_filename, tb_lineno, tb_frame.f_code.co_name, line == null ? "" : " " + line); } /** * Return the specified line of code from filename. * * @param filename a filename String * @param lineno the line number * @return a String line or null */ private String getLine(String filename, int lineno) { RelativeFile file = new RelativeFile(filename); try { if (!file.isFile() || !file.canRead()) { // XXX: We should run through sys.path until the filename is found return null; } } catch (SecurityException e) { return null; // If we don't have read access to the file, return null } PyFile pyFile; try { pyFile = new PyFile(tb_frame.f_code.co_filename, "U", -1); } catch (PyException pye) { return null; } String line = null; int i = 0; try { for (i = 0; i < tb_lineno; i++) { line = pyFile.readline().asString(); if (line.equals("")) { break; } } } catch (PyException pye) { // Proceed to closing the file } try { pyFile.close(); } catch (PyException pye) { // Continue, we may have the line } if (line != null && i == tb_lineno) { i = 0; while (i < line.length()) { char c = line.charAt(i); if (c != ' ' && c != '\t' && c != '\014') { break; } i++; } line = line.substring(i); if (!line.endsWith("\n")) { line += "\n"; } } else { line = null; } return line; } public void dumpStack(StringBuilder buf) { buf.append(tracebackInfo()); if (tb_next != null && tb_next != this) { ((PyTraceback)tb_next).dumpStack(buf); } else if (tb_next == this) { buf.append("circularity detected!"+this+tb_next); } } public String dumpStack() { StringBuilder buf = new StringBuilder(); buf.append("Traceback (most recent call last):\n"); dumpStack(buf); return buf.toString(); } }