python/mozbuild/mozpack/errors.py

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 import sys
     6 from contextlib import contextmanager
     9 class ErrorMessage(Exception):
    10     '''Exception type raised from errors.error() and errors.fatal()'''
    13 class AccumulatedErrors(Exception):
    14     '''Exception type raised from errors.accumulate()'''
    17 class ErrorCollector(object):
    18     '''
    19     Error handling/logging class. A global instance, errors, is provided for
    20     convenience.
    22     Warnings, errors and fatal errors may be logged by calls to the following
    23     functions:
    24         errors.warn(message)
    25         errors.error(message)
    26         errors.fatal(message)
    28     Warnings only send the message on the logging output, while errors and
    29     fatal errors send the message and throw an ErrorMessage exception. The
    30     exception, however, may be deferred. See further below.
    32     Errors may be ignored by calling:
    33         errors.ignore_errors()
    35     After calling that function, only fatal errors throw an exception.
    37     The warnings, errors or fatal errors messages may be augmented with context
    38     information when a context is provided. Context is defined by a pair
    39     (filename, linenumber), and may be set with errors.context() used as a
    40     context manager:
    41         with errors.context(filename, linenumber):
    42             errors.warn(message)
    44     Arbitrary nesting is supported, both for errors.context calls:
    45         with errors.context(filename1, linenumber1):
    46             errors.warn(message)
    47             with errors.context(filename2, linenumber2):
    48                 errors.warn(message)
    50     as well as for function calls:
    51         def func():
    52             errors.warn(message)
    53         with errors.context(filename, linenumber):
    54             func()
    56     Errors and fatal errors can have their exception thrown at a later time,
    57     allowing for several different errors to be reported at once before
    58     throwing. This is achieved with errors.accumulate() as a context manager:
    59         with errors.accumulate():
    60             if test1:
    61                 errors.error(message1)
    62             if test2:
    63                 errors.error(message2)
    65     In such cases, a single AccumulatedErrors exception is thrown, but doesn't
    66     contain information about the exceptions. The logged messages do.
    67     '''
    68     out = sys.stderr
    69     WARN = 1
    70     ERROR = 2
    71     FATAL = 3
    72     _level = ERROR
    73     _context = []
    74     _count = None
    76     def ignore_errors(self, ignore=True):
    77         if ignore:
    78             self._level = self.FATAL
    79         else:
    80             self._level = self.ERROR
    82     def _full_message(self, level, msg):
    83         if level >= self._level:
    84             level = 'Error'
    85         else:
    86             level = 'Warning'
    87         if self._context:
    88             file, line = self._context[-1]
    89             return "%s: %s:%d: %s" % (level, file, line, msg)
    90         return "%s: %s" % (level, msg)
    92     def _handle(self, level, msg):
    93         msg = self._full_message(level, msg)
    94         if level >= self._level:
    95             if self._count is None:
    96                 raise ErrorMessage(msg)
    97             self._count += 1
    98         print >>self.out, msg
   100     def fatal(self, msg):
   101         self._handle(self.FATAL, msg)
   103     def error(self, msg):
   104         self._handle(self.ERROR, msg)
   106     def warn(self, msg):
   107         self._handle(self.WARN, msg)
   109     def get_context(self):
   110         if self._context:
   111             return self._context[-1]
   113     @contextmanager
   114     def context(self, file, line):
   115         if file and line:
   116             self._context.append((file, line))
   117         yield
   118         if file and line:
   119             self._context.pop()
   121     @contextmanager
   122     def accumulate(self):
   123         assert self._count is None
   124         self._count = 0
   125         yield
   126         count = self._count
   127         self._count = None
   128         if count:
   129             raise AccumulatedErrors()
   131     @property
   132     def count(self):
   133         # _count can be None.
   134         return self._count if self._count else 0
   137 errors = ErrorCollector()

mercurial