Loading buildstream/_frontend/app.py +1 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import datetime from textwrap import TextWrapper import click from click import UsageError from blessings import Terminal # Import buildstream public symbols from .. import Scope Loading Loading @@ -92,7 +91,7 @@ class App(): # # Earily initialization # is_a_tty = Terminal().is_a_tty is_a_tty = sys.stdout.isatty() and sys.stderr.isatty() # Enable interactive mode if we're attached to a tty if main_options['no_interactive']: Loading buildstream/_frontend/status.py +76 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ # # Authors: # Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> import os import sys import click from blessings import Terminal import curses # Import a widget internal for formatting time codes from .widget import TimeCode Loading @@ -43,6 +45,13 @@ from .._scheduler import ElementJob # class Status(): # Table of the terminal capabilities we require and use _TERM_CAPABILITIES = { 'move_up': 'cuu1', 'move_x': 'hpa', 'clear_eol': 'el' } def __init__(self, context, content_profile, format_profile, success_profile, error_profile, Loading @@ -56,7 +65,6 @@ class Status(): self._stream = stream self._jobs = [] self._last_lines = 0 # Number of status lines we last printed to console self._term = Terminal() self._spacing = 1 self._colors = colors self._header = _StatusHeader(context, Loading @@ -69,6 +77,7 @@ class Status(): self._alloc_columns = None self._line_length = 0 self._need_alloc = True self._term_caps = self._init_terminal() # add_job() # Loading Loading @@ -121,7 +130,7 @@ class Status(): # def clear(self): if not self._term.does_styling: if not self._term_caps: return for _ in range(self._last_lines): Loading @@ -138,7 +147,7 @@ class Status(): # not necessary to call clear(). def render(self): if not self._term.does_styling: if not self._term_caps: return elapsed = self._stream.elapsed_time Loading Loading @@ -185,6 +194,55 @@ class Status(): ################################################### # Private Methods # ################################################### # _init_terminal() # # Initialize the terminal and return the resolved terminal # capabilities dictionary. # # Returns: # (dict|None): The resolved terminal capabilities dictionary, # or None if the terminal does not support all # of the required capabilities. # def _init_terminal(self): # We need both output streams to be connected to a terminal if not (sys.stdout.isatty() and sys.stderr.isatty()): return None # Initialized terminal, curses might decide it doesnt # support this terminal try: curses.setupterm(os.environ.get('TERM', 'dumb')) except curses.error: return None term_caps = {} # Resolve the string capabilities we need for the capability # names we need. # for capname, capval in self._TERM_CAPABILITIES.items(): code = curses.tigetstr(capval) # If any of the required capabilities resolve empty strings or None, # then we don't have the capabilities we need for a status bar on # this terminal. if not code: return None # Decode sequences as latin1, as they are always 8-bit bytes, # so when b'\xff' is returned, this must be decoded to u'\xff'. # # This technique is employed by the python blessings library # as well, and should provide better compatibility with most # terminals. # term_caps[capname] = code.decode('latin1') return term_caps def _check_term_width(self): term_width, _ = click.get_terminal_size() if self._term_width != term_width: Loading @@ -192,12 +250,24 @@ class Status(): self._need_alloc = True def _move_up(self): assert self._term_caps is not None # Explicitly move to beginning of line, fixes things up # when there was a ^C or ^Z printed to the terminal. click.echo(self._term.move_x(0) + self._term.move_up, nl=False, err=True) move_x = curses.tparm(self._term_caps['move_x'].encode('latin1'), 0) move_x = move_x.decode('latin1') move_up = curses.tparm(self._term_caps['move_up'].encode('latin1')) move_up = move_up.decode('latin1') click.echo(move_x + move_up, nl=False, err=True) def _clear_line(self): click.echo(self._term.clear_eol, nl=False, err=True) assert self._term_caps is not None clear_eol = curses.tparm(self._term_caps['clear_eol'].encode('latin1')) clear_eol = clear_eol.decode('latin1') click.echo(clear_eol, nl=False, err=True) def _allocate(self): if not self._need_alloc: Loading setup.py +0 −1 Original line number Diff line number Diff line Loading @@ -297,7 +297,6 @@ setup(name='BuildStream', 'ruamel.yaml < 0.15.52', 'pluginbase', 'Click', 'blessings >= 1.6', 'jinja2 >= 2.10', 'protobuf >= 3.5', 'grpcio >= 1.10', Loading Loading
buildstream/_frontend/app.py +1 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import datetime from textwrap import TextWrapper import click from click import UsageError from blessings import Terminal # Import buildstream public symbols from .. import Scope Loading Loading @@ -92,7 +91,7 @@ class App(): # # Earily initialization # is_a_tty = Terminal().is_a_tty is_a_tty = sys.stdout.isatty() and sys.stderr.isatty() # Enable interactive mode if we're attached to a tty if main_options['no_interactive']: Loading
buildstream/_frontend/status.py +76 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ # # Authors: # Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> import os import sys import click from blessings import Terminal import curses # Import a widget internal for formatting time codes from .widget import TimeCode Loading @@ -43,6 +45,13 @@ from .._scheduler import ElementJob # class Status(): # Table of the terminal capabilities we require and use _TERM_CAPABILITIES = { 'move_up': 'cuu1', 'move_x': 'hpa', 'clear_eol': 'el' } def __init__(self, context, content_profile, format_profile, success_profile, error_profile, Loading @@ -56,7 +65,6 @@ class Status(): self._stream = stream self._jobs = [] self._last_lines = 0 # Number of status lines we last printed to console self._term = Terminal() self._spacing = 1 self._colors = colors self._header = _StatusHeader(context, Loading @@ -69,6 +77,7 @@ class Status(): self._alloc_columns = None self._line_length = 0 self._need_alloc = True self._term_caps = self._init_terminal() # add_job() # Loading Loading @@ -121,7 +130,7 @@ class Status(): # def clear(self): if not self._term.does_styling: if not self._term_caps: return for _ in range(self._last_lines): Loading @@ -138,7 +147,7 @@ class Status(): # not necessary to call clear(). def render(self): if not self._term.does_styling: if not self._term_caps: return elapsed = self._stream.elapsed_time Loading Loading @@ -185,6 +194,55 @@ class Status(): ################################################### # Private Methods # ################################################### # _init_terminal() # # Initialize the terminal and return the resolved terminal # capabilities dictionary. # # Returns: # (dict|None): The resolved terminal capabilities dictionary, # or None if the terminal does not support all # of the required capabilities. # def _init_terminal(self): # We need both output streams to be connected to a terminal if not (sys.stdout.isatty() and sys.stderr.isatty()): return None # Initialized terminal, curses might decide it doesnt # support this terminal try: curses.setupterm(os.environ.get('TERM', 'dumb')) except curses.error: return None term_caps = {} # Resolve the string capabilities we need for the capability # names we need. # for capname, capval in self._TERM_CAPABILITIES.items(): code = curses.tigetstr(capval) # If any of the required capabilities resolve empty strings or None, # then we don't have the capabilities we need for a status bar on # this terminal. if not code: return None # Decode sequences as latin1, as they are always 8-bit bytes, # so when b'\xff' is returned, this must be decoded to u'\xff'. # # This technique is employed by the python blessings library # as well, and should provide better compatibility with most # terminals. # term_caps[capname] = code.decode('latin1') return term_caps def _check_term_width(self): term_width, _ = click.get_terminal_size() if self._term_width != term_width: Loading @@ -192,12 +250,24 @@ class Status(): self._need_alloc = True def _move_up(self): assert self._term_caps is not None # Explicitly move to beginning of line, fixes things up # when there was a ^C or ^Z printed to the terminal. click.echo(self._term.move_x(0) + self._term.move_up, nl=False, err=True) move_x = curses.tparm(self._term_caps['move_x'].encode('latin1'), 0) move_x = move_x.decode('latin1') move_up = curses.tparm(self._term_caps['move_up'].encode('latin1')) move_up = move_up.decode('latin1') click.echo(move_x + move_up, nl=False, err=True) def _clear_line(self): click.echo(self._term.clear_eol, nl=False, err=True) assert self._term_caps is not None clear_eol = curses.tparm(self._term_caps['clear_eol'].encode('latin1')) clear_eol = clear_eol.decode('latin1') click.echo(clear_eol, nl=False, err=True) def _allocate(self): if not self._need_alloc: Loading
setup.py +0 −1 Original line number Diff line number Diff line Loading @@ -297,7 +297,6 @@ setup(name='BuildStream', 'ruamel.yaml < 0.15.52', 'pluginbase', 'Click', 'blessings >= 1.6', 'jinja2 >= 2.10', 'protobuf >= 3.5', 'grpcio >= 1.10', Loading