Bug 1422302 - Move mozbuild.controller.building.Footer to mozterm r=gps

This makes it a bit easier to share with other parts of the tree,
like test and linting.

MozReview-Commit-ID: 8Gzk8uOF5zK

--HG--
extra : rebase_source : 9354614c78481ca4cbe0327501018a95792e9351
This commit is contained in:
Andrew Halberstadt 2017-12-01 09:59:54 -05:00
Родитель 0e697ce235
Коммит 80e7a5e3f5
4 изменённых файлов: 109 добавлений и 55 удалений

Просмотреть файл

@ -31,6 +31,7 @@ except Exception:
from mach.mixin.logging import LoggingMixin
from mozsystemmonitor.resourcemonitor import SystemResourceMonitor
from mozterm.widgets import Footer
import mozpack.path as mozpath
@ -563,60 +564,6 @@ class TerminalLoggingHandler(logging.Handler):
self.release()
class Footer(object):
"""Handles display of a footer in a terminal.
This class implements the functionality common to all mach commands
that render a footer.
"""
def __init__(self, terminal):
# terminal is a blessings.Terminal.
self._t = terminal
self._fh = sys.stdout
def clear(self):
"""Removes the footer from the current terminal."""
self._fh.write(self._t.move_x(0))
self._fh.write(self._t.clear_eol())
def write(self, parts):
"""Write some output in the footer, accounting for terminal width.
parts is a list of 2-tuples of (encoding_function, input).
None means no encoding."""
# We don't want to write more characters than the current width of the
# terminal otherwise wrapping may result in weird behavior. We can't
# simply truncate the line at terminal width characters because a)
# non-viewable escape characters count towards the limit and b) we
# don't want to truncate in the middle of an escape sequence because
# subsequent output would inherit the escape sequence.
max_width = self._t.width
written = 0
write_pieces = []
for part in parts:
try:
func, part = part
encoded = getattr(self._t, func)(part)
except ValueError:
encoded = part
len_part = len(part)
len_spaces = len(write_pieces)
if written + len_part + len_spaces > max_width:
write_pieces.append(part[0:max_width - written - len_spaces])
written += len_part
break
write_pieces.append(encoded)
written += len_part
with self._t.location():
self._t.move(self._t.height-1,0)
self._fh.write(' '.join(write_pieces))
class BuildProgressFooter(Footer):
"""Handles display of a build progress indicator in a terminal.
@ -651,7 +598,6 @@ class BuildProgressFooter(Footer):
self.write(parts)
class OutputManager(LoggingMixin):
"""Handles writing job output to a terminal or log."""

Просмотреть файл

@ -0,0 +1,58 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import absolute_import, unicode_literals
from .terminal import Terminal
class BaseWidget(object):
def __init__(self, terminal=None):
self.term = terminal or Terminal()
self.stream = self.term.stream
class Footer(BaseWidget):
"""Handles display of a footer in a terminal."""
def clear(self):
"""Removes the footer from the current terminal."""
self.stream.write(self.term.move_x(0))
self.stream.write(self.term.clear_eol())
def write(self, parts):
"""Write some output in the footer, accounting for terminal width.
parts is a list of 2-tuples of (encoding_function, input).
None means no encoding."""
# We don't want to write more characters than the current width of the
# terminal otherwise wrapping may result in weird behavior. We can't
# simply truncate the line at terminal width characters because a)
# non-viewable escape characters count towards the limit and b) we
# don't want to truncate in the middle of an escape sequence because
# subsequent output would inherit the escape sequence.
max_width = self.term.width
written = 0
write_pieces = []
for part in parts:
try:
func, part = part
encoded = getattr(self.term, func)(part)
except ValueError:
encoded = part
len_part = len(part)
len_spaces = len(write_pieces)
if written + len_part + len_spaces > max_width:
write_pieces.append(part[0:max_width - written - len_spaces])
written += len_part
break
write_pieces.append(encoded)
written += len_part
with self.term.location():
self.term.move(self.term.height-1, 0)
self.stream.write(' '.join(write_pieces))

Просмотреть файл

@ -2,3 +2,4 @@
subsuite = mozterm
[test_terminal.py]
[test_widgets.py]

Просмотреть файл

@ -0,0 +1,49 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import absolute_import, unicode_literals
from io import StringIO
import mozunit
import pytest
from mozterm import Terminal
from mozterm.widgets import Footer
@pytest.fixture
def terminal(monkeypatch):
blessings = pytest.importorskip('blessings')
kind = 'xterm-256color'
try:
term = Terminal(stream=StringIO(), force_styling=True, kind=kind)
except blessings.curses.error:
pytest.skip("terminal '{}' not found".format(kind))
# For some reason blessings returns None for width/height though a comment
# says that shouldn't ever happen.
monkeypatch.setattr(term, '_height_and_width', lambda: (100, 100))
return term
def test_footer(terminal):
footer = Footer(terminal=terminal)
footer.write([
('dim', 'foo'),
('green', 'bar'),
])
value = terminal.stream.getvalue()
expected = "\x1b7\x1b[2mfoo\x1b(B\x1b[m \x1b[32mbar\x1b(B\x1b[m\x1b8"
assert value == expected
footer.clear()
value = terminal.stream.getvalue()[len(value):]
expected = "\x1b[1G\x1b[K"
assert value == expected
if __name__ == '__main__':
mozunit.main()