aboutsummaryrefslogtreecommitdiffstats
path: root/debug_toolbar/utils.py
diff options
context:
space:
mode:
authorAymeric Augustin2013-11-16 21:13:50 +0100
committerAymeric Augustin2013-11-16 21:13:50 +0100
commitdbded64743247b18d0f4811dad45739029ae86f3 (patch)
treeece4ea5e43e25fc4dfa828e0c5a80182f3c45b3f /debug_toolbar/utils.py
parent715fe284da176618f5cd404665641d67dc6fc875 (diff)
downloaddjango-debug-toolbar-dbded64743247b18d0f4811dad45739029ae86f3.tar.bz2
Turn package without submodules into module.
Diffstat (limited to 'debug_toolbar/utils.py')
-rw-r--r--debug_toolbar/utils.py192
1 files changed, 192 insertions, 0 deletions
diff --git a/debug_toolbar/utils.py b/debug_toolbar/utils.py
new file mode 100644
index 0000000..c94e19c
--- /dev/null
+++ b/debug_toolbar/utils.py
@@ -0,0 +1,192 @@
+from __future__ import unicode_literals
+
+import inspect
+import os.path
+import django
+import sys
+
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.encoding import force_text
+from django.utils.html import escape
+from django.utils.importlib import import_module
+from django.utils.safestring import mark_safe
+from django.utils import six
+from django.views.debug import linebreak_iter
+
+from .settings import CONFIG
+
+# Figure out some paths
+django_path = os.path.realpath(os.path.dirname(django.__file__))
+
+
+def get_module_path(module_name):
+ try:
+ module = import_module(module_name)
+ except ImportError as e:
+ raise ImproperlyConfigured(
+ 'Error importing HIDDEN_STACKTRACE_MODULES: %s' % (e,))
+ else:
+ source_path = inspect.getsourcefile(module)
+ if source_path.endswith('__init__.py'):
+ source_path = os.path.dirname(source_path)
+ return os.path.realpath(source_path)
+
+
+hidden_paths = [
+ get_module_path(module_name)
+ for module_name in CONFIG['HIDDEN_STACKTRACE_MODULES']
+]
+
+
+def omit_path(path):
+ return any(path.startswith(hidden_path) for hidden_path in hidden_paths)
+
+
+def tidy_stacktrace(stack):
+ """
+ Clean up stacktrace and remove all entries that:
+ 1. Are part of Django (except contrib apps)
+ 2. Are part of socketserver (used by Django's dev server)
+ 3. Are the last entry (which is part of our stacktracing code)
+
+ ``stack`` should be a list of frame tuples from ``inspect.stack()``
+ """
+ trace = []
+ for frame, path, line_no, func_name, text in (f[:5] for f in stack):
+ s_path = os.path.realpath(path)
+ # Support hiding of frames -- used in various utilities that provide
+ # inspection.
+ if CONFIG['HIDE_DJANGO_SQL'] and django_path in s_path and not 'django/contrib' in s_path:
+ continue
+ if omit_path(s_path):
+ continue
+ text = (''.join(force_text(t) for t in text)).strip() if text else ''
+ trace.append((path, line_no, func_name, text))
+ return trace
+
+
+def render_stacktrace(trace):
+ stacktrace = []
+ for frame in trace:
+ params = map(escape, frame[0].rsplit(os.path.sep, 1) + list(frame[1:]))
+ params_dict = dict((six.text_type(idx), v) for idx, v in enumerate(params))
+ try:
+ stacktrace.append('<span class="path">%(0)s/</span>'
+ '<span class="file">%(1)s</span>'
+ ' in <span class="func">%(3)s</span>'
+ '(<span class="lineno">%(2)s</span>)\n'
+ ' <span class="code">%(4)s</span>'
+ % params_dict)
+ except KeyError:
+ # This frame doesn't have the expected format, so skip it and move on to the next one
+ continue
+ return mark_safe('\n'.join(stacktrace))
+
+
+def get_template_info(source, context_lines=3):
+ line = 0
+ upto = 0
+ source_lines = []
+ # before = during = after = ""
+
+ origin, (start, end) = source
+ template_source = origin.reload()
+
+ for num, next in enumerate(linebreak_iter(template_source)):
+ if start >= upto and end <= next:
+ line = num
+ # before = template_source[upto:start]
+ # during = template_source[start:end]
+ # after = template_source[end:next]
+ source_lines.append((num, template_source[upto:next]))
+ upto = next
+
+ top = max(1, line - context_lines)
+ bottom = min(len(source_lines), line + 1 + context_lines)
+
+ context = []
+ for num, content in source_lines[top:bottom]:
+ context.append({
+ 'num': num,
+ 'content': content,
+ 'highlight': (num == line),
+ })
+
+ return {
+ 'name': origin.name,
+ 'context': context,
+ }
+
+
+def get_name_from_obj(obj):
+ if hasattr(obj, '__name__'):
+ name = obj.__name__
+ elif hasattr(obj, '__class__') and hasattr(obj.__class__, '__name__'):
+ name = obj.__class__.__name__
+ else:
+ name = '<unknown>'
+
+ if hasattr(obj, '__module__'):
+ module = obj.__module__
+ name = '%s.%s' % (module, name)
+
+ return name
+
+
+def getframeinfo(frame, context=1):
+ """
+ Get information about a frame or traceback object.
+
+ A tuple of five things is returned: the filename, the line number of
+ the current line, the function name, a list of lines of context from
+ the source code, and the index of the current line within that list.
+ The optional second argument specifies the number of lines of context
+ to return, which are centered around the current line.
+
+ This originally comes from ``inspect`` but is modified to handle issues
+ with ``findsource()``.
+ """
+ if inspect.istraceback(frame):
+ lineno = frame.tb_lineno
+ frame = frame.tb_frame
+ else:
+ lineno = frame.f_lineno
+ if not inspect.isframe(frame):
+ raise TypeError('arg is not a frame or traceback object')
+
+ filename = inspect.getsourcefile(frame) or inspect.getfile(frame)
+ if context > 0:
+ start = lineno - 1 - context // 2
+ try:
+ lines, lnum = inspect.findsource(frame)
+ except Exception: # findsource raises platform-dependant exceptions
+ lines = index = None
+ else:
+ start = max(start, 1)
+ start = max(0, min(start, len(lines) - context))
+ lines = lines[start:(start + context)]
+ index = lineno - 1 - start
+ else:
+ lines = index = None
+
+ if hasattr(inspect, 'Traceback'):
+ return inspect.Traceback(filename, lineno, frame.f_code.co_name, lines, index)
+ else:
+ return (filename, lineno, frame.f_code.co_name, lines, index)
+
+
+def get_stack(context=1):
+ """
+ Get a list of records for a frame and all higher (calling) frames.
+
+ Each record contains a frame object, filename, line number, function
+ name, a list of lines of context, and index within the context.
+
+ Modified version of ``inspect.stack()`` which calls our own ``getframeinfo()``
+ """
+ frame = sys._getframe(1)
+ framelist = []
+ while frame:
+ framelist.append((frame,) + getframeinfo(frame, context))
+ frame = frame.f_back
+ return framelist