Ticket #11834: 11834.patch

File 11834.patch, 8.2 KB (added by Yuri Baburov, 14 years ago)

Patch allowing to customize debug colors.

  • django/views/debug.py

    diff --git a/django/views/debug.py b/django/views/debug.py
    index 6eb7d9f..340aeb0 100644
    a b def technical_500_response(request, exc_type, exc_value, tb): 
    5858    html = reporter.get_traceback_html()
    5959    return HttpResponseServerError(html, mimetype='text/html')
    6060
     61def get_traceback_color_scheme():
     62    """
     63    Use settings.TRACEBACK_COLOR_SCHEME to customize traceback colors.
     64    Format: 'prefix.part': (bg color, wrapper bg color, text color, show details),
     65    any one can be omitted, or replaced with None.
     66    For "show details", possible values are None, True and False,
     67    where True means initially opened, False and None the opposite.
     68    Prefix is written without final dot, and used in
     69    "prefix.part.*"-style pattern matching, where
     70    the first matched pattern is chosen.
     71    Prefix can also be set to None, which means, do never show these stack items.
     72    Unless overridden, installed apps are also colorized,
     73    and special 'INSTALLED_APPS' constant is used for them.
     74    You can also set your own pattern matcher,
     75    please see TRACEBACK_FRAME_COLORS below.
     76    """
     77    TRACEBACK_COLOR_SCHEME = {
     78        'django.template': ('#ffa', '#ffffe2'),
     79        'django.contrib': ('#fda', '#efd'),
     80        'django.utils': ('#cda', '#efd'),
     81        'django.db': ('#cfb', '#efd'),
     82        'django': ('#cfb','#efd'),
     83        'sqlite3': ('#cfe',''),
     84        'psycopg2': ('#cfe',),
     85        'INSTALLED_APPS': ('#ddf', '#fffff2'),
     86        '': ('#bbe', ),
     87    }
     88    scheme = getattr(settings, 'TRACEBACK_COLOR_SCHEME', TRACEBACK_COLOR_SCHEME)
     89    return scheme
     90
     91def get_traceback_frame_colors(module_name, tb_frame):
     92    """
     93    For python module name (like, "django.template.__init__"),
     94    returns the first prefix-matched color. By default, it's
     95    "django.*" rule.
     96    Default colors are passed as empty module_name, if module name
     97    can't be determined, empty string is assumed.
     98    Output format: safe-pattern-name, colors
     99    Colors is tuple of (bg color, wrapper bg color, text color),
     100    last colors can be omitted.
     101    Pattern name is encoded to be safe css class name.
     102    You're able to make your completely own colors matcher,
     103    set TRACEBACK_FRAME_COLORS to your function then.
     104    """
     105    if hasattr(settings, 'TRACEBACK_FRAME_COLORS'):
     106        return getattr(settings, 'TRACEBACK_FRAME_COLORS')(module_name)
     107   
     108    scheme = get_traceback_color_scheme()
     109   
     110    #sort keys so a.b is before a, and empty key is the last
     111    keys = sorted(scheme.keys(), reverse=True)
     112   
     113    for prefix in keys:
     114        if module_name.startswith(prefix+'.') or module_name == prefix:
     115            return prefix
     116
     117    for prefix in getattr(settings, 'INSTALLED_APPS', ()):
     118        if module_name.startswith(prefix+'.') or module_name == prefix:
     119            return 'INSTALLED_APPS'
     120   
     121    return ''
     122
    61123class ExceptionReporter:
    62124    """
    63125    A class to organize and coordinate reporting on exceptions.
    class ExceptionReporter: 
    76138        if isinstance(self.exc_type, basestring):
    77139            self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
    78140            self.exc_type = type(self.exc_value)
    79 
     141   
     142    def get_frame_colors_css(self, existing_types):
     143        required_types = set(['']) | set(existing_types)
     144       
     145        color_fixes = [
     146            '.frame%s div.context ol.context-line li { background-color:%s; }',
     147            'ul.traceback li.frame%s { background-color: %s;}',
     148            '.frame%s div.context ol.context-line li { color:%s; }',
     149        ]
     150        visibility_fixes = [
     151            '.frame%s div.context ol.pre-context { display:block !important; }'
     152            '.frame%s div.context ol.post-context { display:block !important; }'
     153        ]
     154       
     155        scheme = get_traceback_color_scheme()
     156
     157        extra_styles = []
     158       
     159        for frame_type, frame_colors in scheme.iteritems():
     160            classes = frame_type.replace('.','-')
     161            if classes in required_types:
     162                classes = classes and '.'+classes or '' 
     163                for pos, attr in enumerate(frame_colors):
     164                    if attr:
     165                        if pos<3:
     166                            line = color_fixes[pos] % (classes, attr)
     167                            extra_styles.append(line)
     168                        else:
     169                            for fix in visibility_fixes:
     170                                extra_styles.append(fix % classes)
     171        return extra_styles
     172   
    80173    def get_traceback_html(self):
    81174        "Return HTML code for traceback."
    82175
    class ExceptionReporter: 
    107200            self.get_template_exception_info()
    108201
    109202        frames = self.get_traceback_frames()
    110 
     203       
     204        existing_types = [frame['classes'] for frame in frames] 
     205        extra_styles = self.get_frame_colors_css(existing_types)
     206       
    111207        unicode_hint = ''
    112208        if issubclass(self.exc_type, UnicodeError):
    113209            start = getattr(self.exc_value, 'start', None)
    class ExceptionReporter: 
    118214        from django import get_version
    119215        t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
    120216        c = Context({
     217            'extra_styles': '\n    '.join(extra_styles),
    121218            'exception_type': self.exc_type.__name__,
    122219            'exception_value': smart_unicode(self.exc_value, errors='replace'),
    123220            'unicode_hint': unicode_hint,
    class ExceptionReporter: 
    224321            function = tb.tb_frame.f_code.co_name
    225322            lineno = tb.tb_lineno - 1
    226323            loader = tb.tb_frame.f_globals.get('__loader__')
    227             module_name = tb.tb_frame.f_globals.get('__name__')
     324            module_name = tb.tb_frame.f_globals.get('__name__') or ''
     325            classes = get_traceback_frame_colors(module_name, tb.tb_frame)
    228326            pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file(filename, lineno, 7, loader, module_name)
    229327            if pre_context_lineno is not None:
    230328                frames.append({
    231329                    'tb': tb,
     330                    'classes': classes.replace('.','-'),
    232331                    'filename': filename,
    233332                    'function': function,
    234333                    'lineno': lineno + 1,
    TECHNICAL_500_TEMPLATE = """ 
    333432    table.source th { color:#666; }
    334433    table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
    335434    ul.traceback { list-style-type:none; }
    336     ul.traceback li.frame { margin-bottom:1em; }
     435    ul.traceback li.frame { padding-bottom:1em; }
    337436    div.context { margin: 10px 0; }
    338437    div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; }
    339438    div.context ol li { font-family:monospace; white-space:pre; color:#666; cursor:pointer; }
    340     div.context ol.context-line li { color:black; background-color:#ccc; }
     439    div.context ol.context-line li { color:black; }
    341440    div.context ol.context-line li span { float: right; }
    342441    div.commands { margin-left: 40px; }
    343442    div.commands a { color:black; text-decoration:none; }
    TECHNICAL_500_TEMPLATE = """ 
    347446    #template, #template-not-exist { background:#f6f6f6; }
    348447    #template-not-exist ul { margin: 0 0 0 20px; }
    349448    #unicode-hint { background:#eee; }
    350     #traceback { background:#eee; }
     449    #traceback { background-color:#ffe; }
    351450    #requestinfo { background:#f6f6f6; padding-left:120px; }
    352451    #summary table { border:none; background:transparent; }
    353452    #requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
    TECHNICAL_500_TEMPLATE = """ 
    357456    h2 span.commands { font-size:.7em;}
    358457    span.commands a:link {color:#5E5694;}
    359458    pre.exception_value { font-family: sans-serif; color: #666; font-size: 1.5em; margin: 10px 0 10px 0; }
     459    {{ extra_styles }}
    360460  </style>
    361461  <script type="text/javascript">
    362462  //<!--
    TECHNICAL_500_TEMPLATE = """ 
    508608  <div id="browserTraceback">
    509609    <ul class="traceback">
    510610      {% for frame in frames %}
    511         <li class="frame">
     611        <li class="frame {{ frame.classes }}">
    512612          <code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code>
    513613
    514614          {% if frame.context_line %}
Back to Top