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

1from os import kill 

2from collections import OrderedDict 

3from contextlib import suppress 

4from datetime import datetime 

5from os import path 

6from shutil import copyfile 

7 

8 

9from mango.constants import c 

10 

11import sys 

12 

13 

14class _strings(): 

15 

16 if c.t.does_styling: 16 ↛ 17line 16 didn't jump to line 17, because the condition on line 16 was never true

17 u = c.t.underline 

18 HEADER = u + c.t.magenta 

19 OKBLUE = u + c.t.blue 

20 OKGREEN = u + c.t.green 

21 WARNING = u + c.t.yellow 

22 FAIL = u + c.t.red 

23 ENDC = u + c.t.normal 

24 else: 

25 HEADER = '' 

26 OKBLUE = '' 

27 OKGREEN = '' 

28 WARNING = '' 

29 FAIL = '' 

30 ENDC = '' 

31 

32 if c.using_IP: 32 ↛ 33line 32 didn't jump to line 33, because the condition on line 32 was never true

33 tab = '' 

34 else: 

35 tab = " " 

36 

37 _W = ("{}{f}Warning{e}: ".format(tab, f=WARNING, e=ENDC), 9) 

38 _F = ("{}{f}Error{e}: ".format(tab, f=FAIL, e=ENDC), 7) 

39 _G = ("{}{f}D'oh!{e}: ".format(tab, f=OKGREEN, e=ENDC), 7) 

40 _B = ("{}{f}Keyboard Interrupt{e}: ".format(tab, f=OKBLUE, e=ENDC), 20) 

41 _M = ("{}{f}Message{e}: ".format(tab, f=HEADER, e=ENDC), 9) 

42 

43 

44class error(_strings): 

45 """ 

46 Error class. 

47 

48 Handles error printing to the terminal 

49 

50 * All errors are written to stderr 

51 """ 

52 

53 def __init__(self, op=open): 

54 """Init.""" 

55 self.type_e = {"W": self._W, "F": self._F, 

56 "G": self._G, "B": self._B, 

57 "M": self._M, "ME": self._M} 

58 

59 self.error_list = OrderedDict() 

60 self.reprinter = Reprinter() 

61 self.valuehold = 0 

62 self.w_message = True 

63 self.directory = "./" 

64 self.run = 0 

65 self.pids = [] 

66 self.open = op 

67 self.pp = '' 

68 

69 def count(self, etype, msg): 

70 """ 

71 ">" infront of error message will remove call count. 

72 

73 Parameters 

74 ---------- 

75 etype: string 

76 Error type W, F, G, B, M, ME 

77 (Warning, Fatal, Oops, Keyboard, Message, Message exit) 

78 msg: string 

79 message for error 

80 

81 """ 

82 nocount = (etype[0] == '>') 

83 

84 self.etype = etype.replace(">", '') 

85 self.message = '{}{}{}{}'.format(">" if nocount else '', self.type_e[self.etype][0], 

86 msg.replace("\n", "\n" + " " * self.type_e[self.etype][1] + self.tab), 

87 '\n' if self.etype in ['F', 'ME'] else '') 

88 

89 if self.message in self.error_list: 89 ↛ 90line 89 didn't jump to line 90, because the condition on line 89 was never true

90 self.error_list[self.message] += 1 

91 else: 

92 self.error_list[self.message] = 1 

93 

94 self.print() 

95 

96 if self.etype in ["F", "ME"]: 96 ↛ exitline 96 didn't return from function 'count', because the condition on line 96 was never false

97 self._killproc() 

98 

99 def setup(self, w_message, directory, run, pp=0): 

100 """ 

101 Set up for the error system. 

102 

103 Parameters 

104 ---------- 

105 w_message: bool 

106 Turns (most) errors on or off, defaults to on 

107 directory: string 

108 Error save directory 

109 run: int 

110 run number 

111 

112 """ 

113 self.directory = directory 

114 self.w_message = w_message 

115 self.run = run 

116 self.pp = '_pp' if pp == 1 else '' 

117 

118 self.errorfile = "{}/Run{}{}_Errors".format(self.directory, self.run, self.pp) 

119 

120 if path.isfile(self.errorfile): 

121 copyfile(self.errorfile, self.errorfile + "R" + datetime.now().isoformat(timespec='minutes')) 

122 

123 def addpid(self, pid): 

124 """PID collection.""" 

125 self.pids += [pid] 

126 

127 def _killproc(self): 

128 """Fatal error exit.""" 

129 self.endproc() 

130 for i in self.pids: 130 ↛ 131line 130 didn't jump to line 131, because the loop on line 130 never started

131 with suppress(ProcessLookupError): 

132 kill(i, 9) 

133 

134 exit(0) 

135 

136 def endproc(self): 

137 """Write errors to file at end of run.""" 

138 # Possibly dont write file if certain errors exist only TODO 

139 if self.error_list and self.run != 0: 139 ↛ 140line 139 didn't jump to line 140, because the condition on line 139 was never true

140 self._collector() 

141 with self.open(self.errorfile, 'w') as errorfile: 

142 errorfile.write(self.keyhold) 

143 

144 def _collector(self): 

145 self.keyhold = '' 

146 for key, value in self.error_list.copy().items(): 

147 if key[0] == ">": 

148 fkey = key[1:] 

149 elif self.etype == "F" or self.etype == "B": 

150 fkey = key 

151 else: 

152 fkey = key + " x" + str(value) 

153 self.keyhold += fkey + "\n" 

154 

155 def print(self): 

156 """Print errors to screen.""" 

157 if self.w_message or self.etype in ["F", "B", "G", "ME"]: 157 ↛ exitline 157 didn't return from function 'print', because the condition on line 157 was never false

158 self.reprinter.reprint(self.message.strip(">") + "\n") 

159 

160 

161class Reprinter: 

162 """Rewrite terminal output using ANSI escape sequences.""" 

163 

164 def __init__(self): 

165 """Init.""" 

166 self.text = '' 

167 self.frun = True 

168 

169 @staticmethod 

170 def _moveup(): 

171 print(chr(27) + '[9;1H', file=sys.stderr, end='') 

172 

173 def reprint(self, text): 

174 """ 

175 Reprinter. 

176 

177 Parameters 

178 ---------- 

179 text: string 

180 text to be overwritable 

181 

182 """ 

183 if self.frun: 183 ↛ 187line 183 didn't jump to line 187, because the condition on line 183 was never false

184 print(file=sys.stderr) 

185 self.frun = False 

186 # self._moveup() 

187 print(text, file=sys.stderr, end="") 

188 self.text = text 

189 

190 

191def _clientError(Message): 

192 """Raise Kill when asked.""" 

193 # Possible race condition 

194 # Killing threads, writing error to file killed before finished 

195 if Message.startswith("F"): 

196 raise ExitQuiet from None 

197 

198 

199class Quiet(Exception): 

200 """Base Exception for no traceback.""" 

201 

202 pass 

203 

204 

205class ExitQuiet(Quiet): 

206 """Exit Program Quietly Exception.""" 

207 

208 pass 

209 

210 

211def notraceback(kind, message, traceback): 

212 """Exceptionhook only print errors if not Quiet.""" 

213 if Quiet not in kind.__bases__: 

214 if not issubclass(kind, KeyError): 

215 message = ecol(message) 

216 sys.__excepthook__(kind, message, traceback) 

217 else: 

218 message = ecol(message) 

219 sys.stderr.write(message.args[0] + "\n") 

220 

221 

222def ecol(m): 

223 """Colour crash errors.""" 

224 if len(m.args) > 0: 

225 m.args = (_strings.FAIL + f"{m.args[0]}" + _strings.ENDC,) 

226 return m 

227 

228 

229sys.excepthook = notraceback 

230 

231if __name__ == '__main__': 

232 pass