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
9from .registry import register_toolbar_panel, registry
10
11
12class Toolbar:
13 def __init__(self, request):
14 self.request = request
15 self.version = settings.APP_VERSION
16
17 def should_render(self):
18 if settings.DEBUG:
19 return True
20
21 if hasattr(self.request, "impersonator"):
22 return self.request.impersonator.is_admin
23
24 if hasattr(self.request, "user"):
25 return self.request.user.is_admin
26
27 return False
28
29 def request_exception(self):
30 # We can capture the exception currently being handled here, if any.
31 exception = sys.exception()
32
33 if exception and not isinstance(exception, Resolver404):
34 exception._traceback_string = "".join(
35 traceback.format_tb(exception.__traceback__)
36 )
37 return exception
38
39 def get_panels(self):
40 panels = [panel(self.request) for panel in registry.get_panels()]
41
42 if self.request_exception():
43 exception = self.request_exception()
44 panels = [
45 _ExceptionToolbarPanel(self.request, exception),
46 ] + panels
47
48 return panels
49
50
51class ToolbarPanel:
52 name: str
53 template_name: str
54 button_template_name: str = ""
55
56 def __init__(self, request):
57 self.request = request
58
59 def get_template_context(self):
60 return {
61 "request": self.request,
62 "panel": self,
63 }
64
65 def render(self):
66 template = Template(self.template_name)
67 context = self.get_template_context()
68 return mark_safe(template.render(context))
69
70 def render_button(self):
71 """Render the toolbar button for the minimized state."""
72 if not self.button_template_name:
73 return ""
74 template = Template(self.button_template_name)
75 context = self.get_template_context()
76 return mark_safe(template.render(context))
77
78
79class _ExceptionToolbarPanel(ToolbarPanel):
80 name = "Exception"
81 template_name = "toolbar/exception.html"
82 button_template_name = "toolbar/exception_button.html"
83
84 def __init__(self, request, exception):
85 super().__init__(request)
86 self.exception = exception
87
88 def get_template_context(self):
89 context = super().get_template_context()
90 context["exception"] = self.exception
91 return context
92
93
94@register_toolbar_panel
95class _RequestToolbarPanel(ToolbarPanel):
96 name = "Request"
97 template_name = "toolbar/request.html"