| # Printer.py |
| # |
| # Copyright (C) 2012 Carlos Garcia Campos <carlosgc@gnome.org> |
| # |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write to the Free Software |
| # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| from __future__ import absolute_import, division, print_function |
| |
| import sys |
| from Config import Config |
| |
| from threading import RLock |
| |
| |
| _instance = None |
| |
| |
| class Printer: |
| def __init__(self): |
| global _instance |
| if _instance is not None: |
| raise RuntimeError('Printer must not be instantiated more than ' |
| 'once. Use the get_printer() function instead.') |
| |
| self._verbose = Config().verbose |
| self._stream = sys.stdout |
| self._rewrite = self._stream.isatty() and not self._verbose |
| self._current_line_len = 0 |
| self._blocked = 0 |
| |
| self._lock = RLock() |
| |
| _instance = self |
| |
| def _erase_current_line(self): |
| if not self._current_line_len: |
| return |
| |
| line_len = self._current_line_len |
| self._stream.write('\b' * line_len + ' ' * line_len + '\b' * line_len) |
| self._current_line_len = 0 |
| |
| def _ensure_new_line(self, msg): |
| if not msg.endswith('\n'): |
| msg += '\n' |
| return msg |
| |
| def _print(self, msg): |
| self._stream.write(msg) |
| self._stream.flush() |
| |
| def printout(self, msg): |
| if not self._rewrite: |
| self.printout_ln(msg) |
| |
| with self._lock: |
| if self._blocked > 0: |
| return |
| self._erase_current_line() |
| self._print(msg) |
| self._current_line_len = len(msg[msg.rfind('\n') + 1:]) |
| |
| def printout_ln(self, msg=''): |
| with self._lock: |
| if self._blocked > 0: |
| return |
| self._erase_current_line() |
| self._print(self._ensure_new_line(msg)) |
| |
| def printerr(self, msg): |
| with self._lock: |
| if self._blocked > 0: |
| return |
| sys.stderr.write(self._ensure_new_line(msg)) |
| sys.stderr.flush() |
| |
| def print_test_result(self, doc_path, backend_name, n_test, total_tests, msg): |
| self.printout("[%d/%d] %s (%s): %s" % (n_test, total_tests, doc_path, backend_name, msg)) |
| |
| def print_test_result_ln(self, doc_path, backend_name, n_test, total_tests, msg): |
| self.printout_ln("[%d/%d] %s (%s): %s" % (n_test, total_tests, doc_path, backend_name, msg)) |
| |
| def print_default(self, msg): |
| if self._verbose: |
| self.printout_ln(msg) |
| |
| def block(self): |
| with self._lock: |
| self._blocked += 1 |
| |
| def unblock(self): |
| with self._lock: |
| self._blocked -= 1 |
| |
| |
| def get_printer(): |
| if _instance is None: |
| Printer() |
| return _instance |