[Notes] [Git][BuildStream/buildstream][bst-1.2] 2 commits: _frontend/status.py: Completely remove the blessings dependency from BuildStream



Title: GitLab

Tristan Van Berkom pushed to branch bst-1.2 at BuildStream / buildstream

Commits:

3 changed files:

Changes:

  • buildstream/_frontend/app.py
    ... ... @@ -93,7 +93,7 @@ class App():
    93 93
             #
    
    94 94
             # Earily initialization
    
    95 95
             #
    
    96
    -        is_a_tty = Terminal().is_a_tty
    
    96
    +        is_a_tty = sys.stdout.isatty() and sys.stderr.isatty()
    
    97 97
     
    
    98 98
             # Enable interactive mode if we're attached to a tty
    
    99 99
             if main_options['no_interactive']:
    

  • buildstream/_frontend/status.py
    ... ... @@ -16,8 +16,10 @@
    16 16
     #
    
    17 17
     #  Authors:
    
    18 18
     #        Tristan Van Berkom <tristan vanberkom codethink co uk>
    
    19
    +import os
    
    20
    +import sys
    
    19 21
     import click
    
    20
    -from blessings import Terminal
    
    22
    +import curses
    
    21 23
     
    
    22 24
     # Import a widget internal for formatting time codes
    
    23 25
     from .widget import TimeCode
    
    ... ... @@ -43,6 +45,13 @@ from .._scheduler import ElementJob
    43 45
     #
    
    44 46
     class Status():
    
    45 47
     
    
    48
    +    # Table of the terminal capabilities we require and use
    
    49
    +    _TERM_CAPABILITIES = {
    
    50
    +        'move_up': 'cuu1',
    
    51
    +        'move_x': 'hpa',
    
    52
    +        'clear_eol': 'el'
    
    53
    +    }
    
    54
    +
    
    46 55
         def __init__(self, context,
    
    47 56
                      content_profile, format_profile,
    
    48 57
                      success_profile, error_profile,
    
    ... ... @@ -56,7 +65,6 @@ class Status():
    56 65
             self._stream = stream
    
    57 66
             self._jobs = []
    
    58 67
             self._last_lines = 0  # Number of status lines we last printed to console
    
    59
    -        self._term = Terminal()
    
    60 68
             self._spacing = 1
    
    61 69
             self._colors = colors
    
    62 70
             self._header = _StatusHeader(context,
    
    ... ... @@ -69,6 +77,7 @@ class Status():
    69 77
             self._alloc_columns = None
    
    70 78
             self._line_length = 0
    
    71 79
             self._need_alloc = True
    
    80
    +        self._term_caps = self._init_terminal()
    
    72 81
     
    
    73 82
         # add_job()
    
    74 83
         #
    
    ... ... @@ -121,7 +130,7 @@ class Status():
    121 130
         #
    
    122 131
         def clear(self):
    
    123 132
     
    
    124
    -        if not self._term.does_styling:
    
    133
    +        if not self._term_caps:
    
    125 134
                 return
    
    126 135
     
    
    127 136
             for _ in range(self._last_lines):
    
    ... ... @@ -138,7 +147,7 @@ class Status():
    138 147
         # not necessary to call clear().
    
    139 148
         def render(self):
    
    140 149
     
    
    141
    -        if not self._term.does_styling:
    
    150
    +        if not self._term_caps:
    
    142 151
                 return
    
    143 152
     
    
    144 153
             elapsed = self._stream.elapsed_time
    
    ... ... @@ -185,6 +194,55 @@ class Status():
    185 194
         ###################################################
    
    186 195
         #                 Private Methods                 #
    
    187 196
         ###################################################
    
    197
    +
    
    198
    +    # _init_terminal()
    
    199
    +    #
    
    200
    +    # Initialize the terminal and return the resolved terminal
    
    201
    +    # capabilities dictionary.
    
    202
    +    #
    
    203
    +    # Returns:
    
    204
    +    #    (dict|None): The resolved terminal capabilities dictionary,
    
    205
    +    #                 or None if the terminal does not support all
    
    206
    +    #                 of the required capabilities.
    
    207
    +    #
    
    208
    +    def _init_terminal(self):
    
    209
    +
    
    210
    +        # We need both output streams to be connected to a terminal
    
    211
    +        if not (sys.stdout.isatty() and sys.stderr.isatty()):
    
    212
    +            return None
    
    213
    +
    
    214
    +        # Initialized terminal, curses might decide it doesnt
    
    215
    +        # support this terminal
    
    216
    +        try:
    
    217
    +            curses.setupterm(os.environ.get('TERM', 'dumb'))
    
    218
    +        except curses.error:
    
    219
    +            return None
    
    220
    +
    
    221
    +        term_caps = {}
    
    222
    +
    
    223
    +        # Resolve the string capabilities we need for the capability
    
    224
    +        # names we need.
    
    225
    +        #
    
    226
    +        for capname, capval in self._TERM_CAPABILITIES.items():
    
    227
    +            code = curses.tigetstr(capval)
    
    228
    +
    
    229
    +            # If any of the required capabilities resolve empty strings or None,
    
    230
    +            # then we don't have the capabilities we need for a status bar on
    
    231
    +            # this terminal.
    
    232
    +            if not code:
    
    233
    +                return None
    
    234
    +
    
    235
    +            # Decode sequences as latin1, as they are always 8-bit bytes,
    
    236
    +            # so when b'\xff' is returned, this must be decoded to u'\xff'.
    
    237
    +            #
    
    238
    +            # This technique is employed by the python blessings library
    
    239
    +            # as well, and should provide better compatibility with most
    
    240
    +            # terminals.
    
    241
    +            #
    
    242
    +            term_caps[capname] = code.decode('latin1')
    
    243
    +
    
    244
    +        return term_caps
    
    245
    +
    
    188 246
         def _check_term_width(self):
    
    189 247
             term_width, _ = click.get_terminal_size()
    
    190 248
             if self._term_width != term_width:
    
    ... ... @@ -192,12 +250,24 @@ class Status():
    192 250
                 self._need_alloc = True
    
    193 251
     
    
    194 252
         def _move_up(self):
    
    253
    +        assert self._term_caps is not None
    
    254
    +
    
    195 255
             # Explicitly move to beginning of line, fixes things up
    
    196 256
             # when there was a ^C or ^Z printed to the terminal.
    
    197
    -        click.echo(self._term.move_x(0) + self._term.move_up, nl=False, err=True)
    
    257
    +        move_x = curses.tparm(self._term_caps['move_x'].encode('latin1'), 0)
    
    258
    +        move_x = move_x.decode('latin1')
    
    259
    +
    
    260
    +        move_up = curses.tparm(self._term_caps['move_up'].encode('latin1'))
    
    261
    +        move_up = move_up.decode('latin1')
    
    262
    +
    
    263
    +        click.echo(move_x + move_up, nl=False, err=True)
    
    198 264
     
    
    199 265
         def _clear_line(self):
    
    200
    -        click.echo(self._term.clear_eol, nl=False, err=True)
    
    266
    +        assert self._term_caps is not None
    
    267
    +
    
    268
    +        clear_eol = curses.tparm(self._term_caps['clear_eol'].encode('latin1'))
    
    269
    +        clear_eol = clear_eol.decode('latin1')
    
    270
    +        click.echo(clear_eol, nl=False, err=True)
    
    201 271
     
    
    202 272
         def _allocate(self):
    
    203 273
             if not self._need_alloc:
    

  • setup.py
    ... ... @@ -297,7 +297,6 @@ setup(name='BuildStream',
    297 297
               'ruamel.yaml < 0.15.52',
    
    298 298
               'pluginbase',
    
    299 299
               'Click',
    
    300
    -          'blessings >= 1.6',
    
    301 300
               'jinja2 >= 2.10',
    
    302 301
               'protobuf >= 3.5',
    
    303 302
               'grpcio >= 1.10',
    



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]