Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Imports
3from django.conf import settings
4from django.http import Http404
5import os
6from superdjango.patterns import PATTERN_UUID
7from superdjango.views import DetailView, ListView, LoginRequiredMixin, ModelViewSet, TemplateView, ViewSet
8from superdjango.shortcuts import get_model
9from superdjango.utils import read_csv, read_file, File
11# Exports
13__all__ = (
14 "CSVErrorDetail",
15 "CSVErrorList",
16 "CSVErrorViewSet",
17 "ModelErrorDetail",
18 "ModelErrorList",
19 "ModelErrorViewSet",
20)
22# Classes
25class CSVDatabase(File):
26 """The database for CSV error capture."""
28 def __init__(self, path):
29 """Initialize the database.
31 :param path: The path to the CSV file.
32 :type path: str
34 """
35 self.errors = list()
36 self.is_loaded = False
38 super().__init__(path)
40 def __iter__(self):
41 return iter(self.errors)
43 def __len__(self):
44 return len(self.errors)
46 def fetch(self, identifier):
47 """Get the error instance.
49 :param identifier: The unique identifier of the error.
50 :type identifier: str
52 :rtype: CSVError | None
54 """
55 for e in self.errors:
56 if e.identifier == identifier:
57 return e
59 return None
61 def load(self):
62 """Load the database.
64 :rtype: bool
66 """
67 if not self.exists:
68 return False
70 rows = read_csv(self.path, first_row_field_names=True)
71 for row in rows:
72 path = os.path.join(settings.SUPERDJANGO_ERROR_CAPTURE_OUTPUT_PATH, "tracebacks", "%s.txt" % row['id'])
73 if not os.path.exists(path):
74 continue
76 traceback = read_file(path)
78 error = CSVError(
79 added_dt=row['date'],
80 identifier=row['id'],
81 name=row['error'],
82 path=row['path'],
83 line=row['line'],
84 traceback=traceback
85 )
86 self.errors.append(error)
88 self.is_loaded = len(self.errors) > 0
90 return self.is_loaded
93class CSVError(object):
94 """An individual error captured and stored in the CSV database."""
96 def __init__(self, **kwargs):
97 self._attributes = kwargs
99 def __getattr__(self, item):
100 return self._attributes.get(item)
102 @property
103 def file_name(self):
104 """Get the file name where the error occurred.
106 :rtype: str
108 """
109 return self.path.split("/")[-1]
111# Views
114class CSVErrorDetail(LoginRequiredMixin, TemplateView):
115 """Load detail from an error collected by the CSV backend."""
116 pattern_name = "captured_error_detail"
117 pattern_value = "detail/%s/" % PATTERN_UUID
118 template_name = "errors/captured_error_detail.html"
120 def get_context_data(self, **kwargs):
121 context = super().get_context_data(**kwargs)
123 file_path = os.path.join(settings.SUPERDJANGO_ERROR_CAPTURE_OUTPUT_PATH, "current.csv")
124 db = CSVDatabase(file_path)
125 db.load()
127 error = db.fetch(str(self.kwargs['uuid']))
128 if error is None:
129 raise Http404()
131 context['error'] = error
133 return context
136class CSVErrorList(LoginRequiredMixin, TemplateView):
137 """Load errors collected by the CSV backend."""
138 pattern_name = "captured_error_list"
139 pattern_value = ""
140 template_name = "errors/captured_error_list.html"
142 def get_context_data(self, **kwargs):
143 context = super().get_context_data(**kwargs)
145 file_path = os.path.join(settings.SUPERDJANGO_ERROR_CAPTURE_OUTPUT_PATH, "current.csv")
146 db = CSVDatabase(file_path)
147 db.load()
149 context['errors'] = db
151 return context
154class ModelErrorDetail(LoginRequiredMixin, DetailView):
155 """Load detail from an error collected by the Model backend."""
156 context_object_name = "error"
157 pattern_name = "captured_error_detail"
158 pattern_value = "detail/%s/" % PATTERN_UUID
159 template_name = "errors/captured_error_detail.html"
161 @classmethod
162 def get_model(cls):
163 """Override to provide developer-defined model."""
164 return get_model(settings.SUPERDJANGO_ERROR_CAPTURE_MODEL_NAME, raise_exception=False)
167class ModelErrorList(LoginRequiredMixin, ListView):
168 """Load errors collected by the Model backend."""
169 context_object_name = "errors"
170 pattern_name = "captured_error_list"
171 pattern_value = ""
172 template_name = "errors/captured_error_list.html"
174 @classmethod
175 def get_model(cls):
176 """Override to provide developer-defined model."""
177 return get_model(settings.SUPERDJANGO_ERROR_CAPTURE_MODEL_NAME, raise_exception=False)
180# View Sets
183class CSVErrorViewSet(ViewSet):
184 """Collects views for displaying errors logged to CSV."""
185 views = [
186 CSVErrorDetail,
187 CSVErrorList,
188 ]
191class ModelErrorViewSet(ModelViewSet):
192 """Collects views for displaying errors logged to the database."""
193 views = [
194 ModelErrorDetail,
195 ModelErrorList,
196 ]