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"