Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2013 The LUCI Authors. All rights reserved. | 1 # Copyright 2013 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import contextlib | 5 import contextlib |
| 6 import functools | 6 import functools |
| 7 import os | 7 import os |
| 8 import sys | 8 import sys |
| 9 import traceback | 9 import traceback |
| 10 import urllib | 10 import urllib |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 self.lines[-1].write(s) | 183 self.lines[-1].write(s) |
| 184 break | 184 break |
| 185 self.lines[-1].write(s[:i]) | 185 self.lines[-1].write(s[:i]) |
| 186 self.lines[-1] = self.lines[-1].getvalue() | 186 self.lines[-1] = self.lines[-1].getvalue() |
| 187 self.lines.append(StringIO()) | 187 self.lines.append(StringIO()) |
| 188 s = s[i+1:] | 188 s = s[i+1:] |
| 189 | 189 |
| 190 def close(self): | 190 def close(self): |
| 191 if not isinstance(self.lines[-1], basestring): | 191 if not isinstance(self.lines[-1], basestring): |
| 192 self.lines[-1] = self.lines[-1].getvalue() | 192 self.lines[-1] = self.lines[-1].getvalue() |
| 193 | |
| 194 | |
| 195 class MultiException(Exception): | |
| 196 """An exception that aggregates multiple exceptions and summarizes them.""" | |
| 197 | |
| 198 def __init__(self): | |
| 199 self._inner = [] | |
| 200 | |
| 201 def append(self, exc): | |
| 202 assert isinstance(exc, BaseException) | |
| 203 self._inner.append(exc) | |
| 204 | |
| 205 def __nonzero__(self): | |
| 206 return bool(self._inner) | |
| 207 | |
| 208 def __str__(self): | |
| 209 if len(self._inner) == 0: | |
| 210 text = 'No exceptions' | |
| 211 elif len(self._inner) == 1: | |
| 212 text = str(self._inner[0]) | |
| 213 else: | |
| 214 text = str(self._inner[0]) + ', and %d more...' % (len(self._inner)-1) | |
| 215 return '%s(%s)' % (type(self).__name__, text) | |
| 216 | |
| 217 def raise_if_any(self): | |
| 218 if self: | |
|
martiniss
2016/09/01 21:59:48
Shouldn't this be "if self._inner"?
dnj
2016/09/07 17:54:58
Done.
| |
| 219 raise self | |
| 220 | |
| 221 @contextlib.contextmanager | |
| 222 def catch(self): | |
| 223 try: | |
| 224 yield | |
| 225 except Exception as e: | |
|
martiniss
2016/09/01 21:59:48
Can you make the exception class a required parame
dnj
2016/09/07 17:54:58
Sure.
However, note the only user ("defer_excepti
| |
| 226 self.append(e) | |
| 227 | |
| 228 | |
| 229 def defer_exceptions_for(gen): | |
| 230 mexc = MultiException() | |
| 231 for e in gen: | |
| 232 try: | |
| 233 yield e | |
| 234 except Exception as e: | |
| 235 exc.append(e) | |
| 236 mexc.raise_if_any() | |
| OLD | NEW |