From a17a65a5c012327d2bfff047aa3dddfb730fadd6 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sat, 16 Jun 2007 00:47:27 +0200 Subject: [PATCH] [svn] some small code cleanups in jinja --HG-- branch : trunk --- jinja/_debugger.c | 8 ++++++-- jinja/_native.py | 16 ++++------------ jinja/debugger.py | 35 ++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/jinja/_debugger.c b/jinja/_debugger.c index 203cd84..111d825 100644 --- a/jinja/_debugger.c +++ b/jinja/_debugger.c @@ -6,6 +6,10 @@ * on traceback objects. This is required to inject a traceback into * another one. * + * For better windows support (not everybody has a visual studio 2003 + * at home) it would be a good thing to have a ctypes implementation, but + * because the struct is not exported there is currently no sane way. + * * :copyright: 2007 by Armin Ronacher. * :license: BSD, see LICENSE for more details. */ @@ -23,7 +27,8 @@ tb_set_next(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "OO", &tb, &next)) return NULL; - if (!(PyTraceBack_Check(tb) && (PyTraceBack_Check(next) || next == Py_None))) { + if (!(PyTraceBack_Check(tb) && (PyTraceBack_Check(next) || + next == Py_None))) { PyErr_SetString(PyExc_TypeError, "traceback object required."); return NULL; } @@ -41,7 +46,6 @@ static PyMethodDef module_methods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; - #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ #define PyMODINIT_FUNC void #endif diff --git a/jinja/_native.py b/jinja/_native.py index 1c01fa0..1d9747a 100644 --- a/jinja/_native.py +++ b/jinja/_native.py @@ -34,9 +34,7 @@ class BaseContext(object): stack = property(stack) def pop(self): - """ - Pop the last layer from the stack and return it. - """ + """Pop the last layer from the stack and return it.""" rv = self._pop() self.current = self._stack[0] return rv @@ -71,22 +69,16 @@ class BaseContext(object): return self._undefined_singleton def __setitem__(self, name, value): - """ - Set a variable in the outermost layer. - """ + """Set a variable in the outermost layer.""" self.current[name] = value def __delitem__(self, name): - """ - Delete an variable in the outermost layer. - """ + """Delete a variable in the outermost layer.""" if name in self.current: del self.current[name] def __contains__(self, name): - """ - Check if the context contains a given variable. - """ + """ Check if the context contains a given variable.""" for layer in self._stack: if name in layer: return True diff --git a/jinja/debugger.py b/jinja/debugger.py index 396c665..bc60272 100644 --- a/jinja/debugger.py +++ b/jinja/debugger.py @@ -3,7 +3,34 @@ jinja.debugger ~~~~~~~~~~~~~~ - The debugger module of awesomeness. + This module implements helper function Jinja uses to give the users a + possibility to develop Jinja templates like they would debug python code. + It seamlessly integreates into the python traceback system, in fact it + just modifies the trackback stack so that the line numbers are correct + and the frame information are bound to the context and not the frame of + the template evaluation loop. + + To achive this it raises the exception it cought before in an isolated + namespace at a given line. The locals namespace is set to the current + template context. + + The traceback generated by raising that exception is then either returned + or linked with the former traceback if the `jinja._debugger` module is + available. Because it's not possible to modify traceback objects from the + python space this module is needed for this process. + + If it's not available it just ignores the other frames. Because this can + lead to actually harder to debug code there is a setting on the jinja + environment to disable the debugging system. + + The isolated namespace which is used to raise the exception also contains + a `__loader__` name that helds a reference to a PEP 302 compatible loader. + Because there are currently some traceback systems (such as the paste + evalexception debugger) that do not provide the frame globals when + retrieving the source from the linecache module, Jinja injects the source + to the linecache module itself and changes the filename to a URL style + "virtual filename" so that Jinja doesn't acidentally override other files + in the linecache. :copyright: 2007 by Armin Ronacher. :license: BSD, see LICENSE for more details. @@ -50,7 +77,7 @@ def fake_template_exception(exc_type, exc_value, traceback, filename, lineno, filename = filename.encode('utf-8') # generate an jinja unique filename used so that linecache - # gets data that doesn't interferes with other modules + # gets data that doesn't interfere with other modules if filename is None: vfilename = 'jinja://~%d' % randrange(0, 10000) filename = '' @@ -78,7 +105,8 @@ def fake_template_exception(exc_type, exc_value, traceback, filename, lineno, except: exc_info = sys.exc_info() - # if we have an extended debugger we set the tb_next flag + # if we have an extended debugger we set the tb_next flag so that + # we don't loose the higher stack items. if has_extended_debugger and traceback is not None: tb_set_next(exc_info[2].tb_next, traceback.tb_next) @@ -154,6 +182,7 @@ class TracebackLoader(object): ) def get_source(self, impname): + """Return the source as bytestring.""" source = '' if self.source is not None: source = self.source -- 2.26.2