Plain is headed towards 1.0! Subscribe for development updates →

  1import sys
  2import traceback
  3
  4from plain.runtime import settings
  5from plain.templates import Template
  6from plain.urls.exceptions import Resolver404
  7from plain.utils.safestring import mark_safe
  8
  9
 10class Toolbar:
 11    def __init__(self, request):
 12        self.request = request
 13        self.version = settings.ADMIN_TOOLBAR_VERSION
 14
 15    def should_render(self):
 16        if settings.DEBUG:
 17            return True
 18
 19        if hasattr(self.request, "impersonator"):
 20            return self.request.impersonator.is_admin
 21
 22        if self.request.user:
 23            return self.request.user.is_admin
 24
 25        return False
 26
 27    def request_exception(self):
 28        # We can capture the exception currently being handled here, if any.
 29        exception = sys.exception()
 30
 31        if exception and not isinstance(exception, Resolver404):
 32            exception._traceback_string = "".join(
 33                traceback.format_tb(exception.__traceback__)
 34            )
 35            return exception
 36
 37    def get_panels(self):
 38        panels = [panel(self.request) for panel in _toolbar_panel_registry.get_panels()]
 39
 40        if self.request_exception():
 41            exception = self.request_exception()
 42            panels = [
 43                _ExceptionToolbarPanel(self.request, exception),
 44            ] + panels
 45
 46        return panels
 47
 48
 49class ToolbarPanel:
 50    name: str
 51    template_name: str
 52
 53    def __init__(self, request):
 54        self.request = request
 55
 56    def get_template_context(self):
 57        return {
 58            "request": self.request,
 59        }
 60
 61    def render(self):
 62        template = Template(self.template_name)
 63        context = self.get_template_context()
 64        return mark_safe(template.render(context))
 65
 66
 67class _ToolbarPanelRegistry:
 68    def __init__(self):
 69        self._panels = {}
 70
 71    def register_panel(self, panel_class):
 72        self._panels[panel_class.name] = panel_class
 73
 74    def get_panels(self):
 75        return self._panels.values()
 76
 77
 78_toolbar_panel_registry = _ToolbarPanelRegistry()
 79
 80
 81def register_toolbar_panel(panel_class):
 82    _toolbar_panel_registry.register_panel(panel_class)
 83    return panel_class
 84
 85
 86class _ExceptionToolbarPanel(ToolbarPanel):
 87    name = "Exception"
 88    template_name = "toolbar/exception.html"
 89
 90    def __init__(self, request, exception):
 91        super().__init__(request)
 92        self.exception = exception
 93
 94    def get_template_context(self):
 95        context = super().get_template_context()
 96        context["exception"] = self.exception
 97        return context
 98
 99
100@register_toolbar_panel
101class _RequestToolbarPanel(ToolbarPanel):
102    name = "Request"
103    template_name = "toolbar/request.html"
104
105
106@register_toolbar_panel
107class _QuerystatsToolbarPanel(ToolbarPanel):
108    name = "Queries"
109    template_name = "toolbar/querystats.html"