1 """
2 Common error handling facilities for user interface components.
3 """
4
5
6
7
8
9
10
11 import re
12 import sys
13 import textwrap
14 import traceback
15
16 from gavo import base
17 from gavo import grammars
18 from gavo import rsc
19 from gavo import utils
20
21
53
54
63
64
71
72
82
83
85 """raises the current exception and tries write a good error message
86 for it.
87
88 opts can be an object with some attribute (read the source); this
89 usually comes from user.cli's main.
90
91 output must be a function accepting a single string, defaulting to
92 something just encoding the string for the output found and dumping
93 it to stderr.
94
95 The function returns a suggested return value for the whole program.
96 """
97
98
99
100
101
102 retval = 1
103 messages = []
104 try:
105 raise
106 except SystemExit as msg:
107 retval = msg.code
108 except KeyboardInterrupt:
109 retval = 2
110 except grammars.ParseError as msg:
111 if msg.location:
112 messages.append("Parse error at %s: %s"%(msg.location,
113 utils.safe_str(msg)))
114 else:
115 messages.append("Parse error: %s"%utils.safe_str(msg))
116 if msg.record:
117 messages.append("")
118 messages.append("Offending input was:\n")
119 messages.append(repr(msg.record)+"\n")
120
121 except base.SourceParseError as msg:
122 messages.append("While parsing source %s, near %s:\n"%(
123 msg.source, msg.location))
124 messages.append((msg.msg+"\n").decode("iso-8859-1", "ignore"))
125 if msg.offending:
126 messages.append("Offending literal: %s\n"%repr(msg.offending))
127
128 except base.BadCode as msg:
129 messages.append("Bad user %s: %s\n"%(msg.codeType, str(msg.origExc)))
130 if msg.pos:
131 messages.append("(At %s)"%msg.pos)
132
133 except rsc.DBTableError as msg:
134 messages.append("While building table %s: %s"%(msg.qName,
135 msg))
136
137 except base.MetaError as msg:
138 messages.append("While working on metadata of '%s': %s"%(
139 str(msg.carrier),
140 str(msg.__class__.__name__)))
141 if getattr(msg, "pos", None):
142 messages.append("in element starting at %s:"%msg.pos)
143 if msg.key is not None:
144 messages.append("-- key %s --"%msg.key)
145 messages.append(utils.safe_str(msg))
146
147 except (base.ValidationError, base.ReportableError,
148 base.LiteralParseError, base.StructureError, base.NotFoundError,
149 base.MetaValidationError) as msg:
150
151 if not getattr(msg, "posInMsg", False):
152 if getattr(msg, "pos", None):
153 messages.append("At or near %s:"%msg.pos)
154 elif getattr(msg, "inFile", None):
155 messages.append("In %s:"%msg.inFile)
156
157 if getattr(msg, "row", None):
158 row = dict((key, value) for key, value in msg.row.iteritems()
159 if key and not key.startswith("_") and not key.endswith("_"))
160 messages.append(" Row\n %s"%formatRow(row))
161 messages.append(" ")
162 messages.append(str(msg).decode("iso-8859-1", "ignore"))
163
164 except base.DataError as msg:
165 messages.append("Error in input data:")
166 messages.append(utils.safe_str(msg))
167
168 except Exception as msg:
169 if hasattr(msg, "excRow"):
170 messages.append("Snafu in %s, %s\n"%(msg.excRow, msg.excCol))
171 messages.append("")
172 messages.append("Oops. Unhandled exception %s.\n"%msg.__class__.__name__)
173 messages.append("Exception payload: %s"%utils.safe_str(msg))
174 base.ui.notifyError("Uncaught exception at toplevel")
175
176 if getattr(opts, "enablePDB", False):
177 raise
178 elif getattr(opts, "alwaysTracebacks", False):
179 traceback.print_exc()
180 if messages:
181 errTx = utils.safe_str("*** Error: "+"\n".join(messages))
182 output(reformatMessage(errTx)+"\n")
183 if getattr(opts, "showHints", True) and getattr(msg, "hint", None):
184 output(reformatMessage("Hint: "+msg.hint)+"\n")
185
186 return retval
187
188
190 """A fake cli operation just raising exceptions.
191
192 This is mainly for testing and development.
193 """
194 if len(sys.argv)<2:
195 raise ValueError("Too short")
196 arg = sys.argv[1]
197 if arg=="--help":
198 raise base.Error("Hands off this. For Developers only")
199