mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-07-07 10:29:03 +00:00
140 lines
4.0 KiB
Python
140 lines
4.0 KiB
Python
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||
|
|
||
|
from __future__ import absolute_import
|
||
|
|
||
|
import sys
|
||
|
from contextlib import contextmanager
|
||
|
|
||
|
|
||
|
class ErrorMessage(Exception):
|
||
|
'''Exception type raised from errors.error() and errors.fatal()'''
|
||
|
|
||
|
|
||
|
class AccumulatedErrors(Exception):
|
||
|
'''Exception type raised from errors.accumulate()'''
|
||
|
|
||
|
|
||
|
class ErrorCollector(object):
|
||
|
'''
|
||
|
Error handling/logging class. A global instance, errors, is provided for
|
||
|
convenience.
|
||
|
|
||
|
Warnings, errors and fatal errors may be logged by calls to the following
|
||
|
functions:
|
||
|
errors.warn(message)
|
||
|
errors.error(message)
|
||
|
errors.fatal(message)
|
||
|
|
||
|
Warnings only send the message on the logging output, while errors and
|
||
|
fatal errors send the message and throw an ErrorMessage exception. The
|
||
|
exception, however, may be deferred. See further below.
|
||
|
|
||
|
Errors may be ignored by calling:
|
||
|
errors.ignore_errors()
|
||
|
|
||
|
After calling that function, only fatal errors throw an exception.
|
||
|
|
||
|
The warnings, errors or fatal errors messages may be augmented with context
|
||
|
information when a context is provided. Context is defined by a pair
|
||
|
(filename, linenumber), and may be set with errors.context() used as a
|
||
|
context manager:
|
||
|
with errors.context(filename, linenumber):
|
||
|
errors.warn(message)
|
||
|
|
||
|
Arbitrary nesting is supported, both for errors.context calls:
|
||
|
with errors.context(filename1, linenumber1):
|
||
|
errors.warn(message)
|
||
|
with errors.context(filename2, linenumber2):
|
||
|
errors.warn(message)
|
||
|
|
||
|
as well as for function calls:
|
||
|
def func():
|
||
|
errors.warn(message)
|
||
|
with errors.context(filename, linenumber):
|
||
|
func()
|
||
|
|
||
|
Errors and fatal errors can have their exception thrown at a later time,
|
||
|
allowing for several different errors to be reported at once before
|
||
|
throwing. This is achieved with errors.accumulate() as a context manager:
|
||
|
with errors.accumulate():
|
||
|
if test1:
|
||
|
errors.error(message1)
|
||
|
if test2:
|
||
|
errors.error(message2)
|
||
|
|
||
|
In such cases, a single AccumulatedErrors exception is thrown, but doesn't
|
||
|
contain information about the exceptions. The logged messages do.
|
||
|
'''
|
||
|
out = sys.stderr
|
||
|
WARN = 1
|
||
|
ERROR = 2
|
||
|
FATAL = 3
|
||
|
_level = ERROR
|
||
|
_context = []
|
||
|
_count = None
|
||
|
|
||
|
def ignore_errors(self, ignore=True):
|
||
|
if ignore:
|
||
|
self._level = self.FATAL
|
||
|
else:
|
||
|
self._level = self.ERROR
|
||
|
|
||
|
def _full_message(self, level, msg):
|
||
|
if level >= self._level:
|
||
|
level = 'Error'
|
||
|
else:
|
||
|
level = 'Warning'
|
||
|
if self._context:
|
||
|
file, line = self._context[-1]
|
||
|
return "%s: %s:%d: %s" % (level, file, line, msg)
|
||
|
return "%s: %s" % (level, msg)
|
||
|
|
||
|
def _handle(self, level, msg):
|
||
|
msg = self._full_message(level, msg)
|
||
|
if level >= self._level:
|
||
|
if self._count is None:
|
||
|
raise ErrorMessage(msg)
|
||
|
self._count += 1
|
||
|
print >>self.out, msg
|
||
|
|
||
|
def fatal(self, msg):
|
||
|
self._handle(self.FATAL, msg)
|
||
|
|
||
|
def error(self, msg):
|
||
|
self._handle(self.ERROR, msg)
|
||
|
|
||
|
def warn(self, msg):
|
||
|
self._handle(self.WARN, msg)
|
||
|
|
||
|
def get_context(self):
|
||
|
if self._context:
|
||
|
return self._context[-1]
|
||
|
|
||
|
@contextmanager
|
||
|
def context(self, file, line):
|
||
|
if file and line:
|
||
|
self._context.append((file, line))
|
||
|
yield
|
||
|
if file and line:
|
||
|
self._context.pop()
|
||
|
|
||
|
@contextmanager
|
||
|
def accumulate(self):
|
||
|
assert self._count is None
|
||
|
self._count = 0
|
||
|
yield
|
||
|
count = self._count
|
||
|
self._count = None
|
||
|
if count:
|
||
|
raise AccumulatedErrors()
|
||
|
|
||
|
@property
|
||
|
def count(self):
|
||
|
# _count can be None.
|
||
|
return self._count if self._count else 0
|
||
|
|
||
|
|
||
|
errors = ErrorCollector()
|