Hide keyboard shortcuts

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 

2 

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 

10 

11# Exports 

12 

13__all__ = ( 

14 "CSVErrorDetail", 

15 "CSVErrorList", 

16 "CSVErrorViewSet", 

17 "ModelErrorDetail", 

18 "ModelErrorList", 

19 "ModelErrorViewSet", 

20) 

21 

22# Classes 

23 

24 

25class CSVDatabase(File): 

26 """The database for CSV error capture.""" 

27 

28 def __init__(self, path): 

29 """Initialize the database. 

30 

31 :param path: The path to the CSV file. 

32 :type path: str 

33 

34 """ 

35 self.errors = list() 

36 self.is_loaded = False 

37 

38 super().__init__(path) 

39 

40 def __iter__(self): 

41 return iter(self.errors) 

42 

43 def __len__(self): 

44 return len(self.errors) 

45 

46 def fetch(self, identifier): 

47 """Get the error instance. 

48 

49 :param identifier: The unique identifier of the error. 

50 :type identifier: str 

51 

52 :rtype: CSVError | None 

53 

54 """ 

55 for e in self.errors: 

56 if e.identifier == identifier: 

57 return e 

58 

59 return None 

60 

61 def load(self): 

62 """Load the database. 

63 

64 :rtype: bool 

65 

66 """ 

67 if not self.exists: 

68 return False 

69 

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 

75 

76 traceback = read_file(path) 

77 

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) 

87 

88 self.is_loaded = len(self.errors) > 0 

89 

90 return self.is_loaded 

91 

92 

93class CSVError(object): 

94 """An individual error captured and stored in the CSV database.""" 

95 

96 def __init__(self, **kwargs): 

97 self._attributes = kwargs 

98 

99 def __getattr__(self, item): 

100 return self._attributes.get(item) 

101 

102 @property 

103 def file_name(self): 

104 """Get the file name where the error occurred. 

105 

106 :rtype: str 

107 

108 """ 

109 return self.path.split("/")[-1] 

110 

111# Views 

112 

113 

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" 

119 

120 def get_context_data(self, **kwargs): 

121 context = super().get_context_data(**kwargs) 

122 

123 file_path = os.path.join(settings.SUPERDJANGO_ERROR_CAPTURE_OUTPUT_PATH, "current.csv") 

124 db = CSVDatabase(file_path) 

125 db.load() 

126 

127 error = db.fetch(str(self.kwargs['uuid'])) 

128 if error is None: 

129 raise Http404() 

130 

131 context['error'] = error 

132 

133 return context 

134 

135 

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" 

141 

142 def get_context_data(self, **kwargs): 

143 context = super().get_context_data(**kwargs) 

144 

145 file_path = os.path.join(settings.SUPERDJANGO_ERROR_CAPTURE_OUTPUT_PATH, "current.csv") 

146 db = CSVDatabase(file_path) 

147 db.load() 

148 

149 context['errors'] = db 

150 

151 return context 

152 

153 

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" 

160 

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) 

165 

166 

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" 

173 

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) 

178 

179 

180# View Sets 

181 

182 

183class CSVErrorViewSet(ViewSet): 

184 """Collects views for displaying errors logged to CSV.""" 

185 views = [ 

186 CSVErrorDetail, 

187 CSVErrorList, 

188 ] 

189 

190 

191class ModelErrorViewSet(ModelViewSet): 

192 """Collects views for displaying errors logged to the database.""" 

193 views = [ 

194 ModelErrorDetail, 

195 ModelErrorList, 

196 ]