def __init__(self, stream, term=None, forcetty=False, encoding=None): """Initialize. :type stream: file-like object. :param stream: stream to output to, defaulting to :py:class:`sys.stdout`. :type term: string. :param term: terminal type, pulled from the environment if omitted. :type forcetty: bool :param forcetty: force output of colors even if the wrapped stream is not a tty. """ PlainTextFormatter.__init__(self, stream, encoding=encoding) fd = stream.fileno() if term is None: # We only apply the remapping if we are guessing the # terminal type from the environment. If we get a term # type passed explicitly we just use it as-is (if the # caller wants the remap just doing the # term_alternates lookup there is easy enough.) term_env = os.environ.get('TERM') term_alt = self.term_alternates.get(term_env) for term in (term_alt, term_env): if term is not None: try: curses.setupterm(fd=fd, term=term) except curses.error: pass else: break else: raise TerminfoDisabled( 'no terminfo entries, not even for "dumb"?') else: # TODO maybe do something more useful than raising curses.error # if term is not in the terminfo db here? curses.setupterm(fd=fd, term=term) self._term = term self.width = curses.tigetnum('cols') try: self.reset = TerminfoReset(curses.tigetstr('sgr0')) self.bold = TerminfoMode(curses.tigetstr('bold')) self.underline = TerminfoMode(curses.tigetstr('smul')) self._color_reset = curses.tigetstr('op') self._set_color = (curses.tigetstr('setaf'), curses.tigetstr('setab')) except (_BogusTerminfo, curses.error): compatibility.raise_from(TerminfoHatesOurTerminal(self._term)) if not all(self._set_color): raise TerminfoDisabled( 'setting background/foreground colors is not supported') curses.tparm(self._set_color[0], curses.COLOR_WHITE) # [fg, bg] self._current_colors = [None, None] self._modes = set() self._pos = 0 self._fg_cache = defaultdictkey(partial(TerminfoColor, 0)) self._bg_cache = defaultdictkey(partial(TerminfoColor, 1))
def write(self, *args, **kwargs): PlainTextFormatter.write(self, *args, **kwargs) try: if self._modes: self.reset(self) if self._current_colors != [None, None]: self._current_colors = [None, None] self.stream.write(self._color_reset) except IOError as e: if e.errno == errno.EPIPE: raise StreamClosed(e) raise
def get_formatter(stream, force_color=False): """TerminfoFormatter if the stream is a tty, else PlainTextFormatter.""" if TerminfoColor is None: return PlainTextFormatter(stream) try: fd = stream.fileno() except fileno_excepts: pass else: # We do this instead of stream.isatty() because TerminfoFormatter # needs an fd to pass to curses, not just a filelike talking to a tty. if os.isatty(fd) or force_color: try: return TerminfoFormatter(stream) except (curses.error, TerminfoDisabled, TerminfoHatesOurTerminal): # This happens if TERM is unset and possibly in more cases. # Just fall back to the PlainTextFormatter. pass return PlainTextFormatter(stream)
def __init__(self, stream, term=None, forcetty=False, encoding=None): """Initialize. :type stream: file-like object. :param stream: stream to output to, defaulting to :py:class:`sys.stdout`. :type term: string. :param term: terminal type, pulled from the environment if omitted. :type forcetty: bool :param forcetty: force output of colors even if the wrapped stream is not a tty. """ PlainTextFormatter.__init__(self, stream, encoding=encoding) fd = stream.fileno() if term is None: # We only apply the remapping if we are guessing the # terminal type from the environment. If we get a term # type passed explicitly we just use it as-is (if the # caller wants the remap just doing the # term_alternates lookup there is easy enough.) term_env = os.environ.get('TERM') term_alt = self.term_alternates.get(term_env) for term in (term_alt, term_env): if term is not None: try: curses.setupterm(fd=fd, term=term) except curses.error: pass else: break else: raise TerminfoDisabled( 'no terminfo entries, not even for "dumb"?') else: # TODO maybe do something more useful than raising curses.error # if term is not in the terminfo db here? curses.setupterm(fd=fd, term=term) self._term = term self.width = curses.tigetnum('cols') try: self.reset = TerminfoReset(curses.tigetstr('sgr0')) self.bold = TerminfoMode(curses.tigetstr('bold')) self.underline = TerminfoMode(curses.tigetstr('smul')) self._color_reset = curses.tigetstr('op') self._set_color = ( curses.tigetstr('setaf'), curses.tigetstr('setab')) except (_BogusTerminfo, curses.error): compatibility.raise_from(TerminfoHatesOurTerminal(self._term)) if not all(self._set_color): raise TerminfoDisabled( 'setting background/foreground colors is not supported') curses.tparm(self._set_color[0], curses.COLOR_WHITE) # [fg, bg] self._current_colors = [None, None] self._modes = set() self._pos = 0 self._fg_cache = defaultdictkey(partial(TerminfoColor, 0)) self._bg_cache = defaultdictkey(partial(TerminfoColor, 1))