Bug 1552897 - Ride along: format with black r=ahal

Depends on D31807

Differential Revision: https://phabricator.services.mozilla.com/D31808

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Sylvestre Ledru 2019-05-23 16:44:04 +00:00
parent d56df326cf
commit 6446b8a5f0
3 changed files with 127 additions and 103 deletions

View File

@ -13,23 +13,25 @@ from ..util.string import pluralize
class StylishFormatter(object):
"""Formatter based on the eslint default."""
_indent_ = ' '
_indent_ = " "
# Colors later on in the list are fallbacks in case the terminal
# doesn't support colors earlier in the list.
# See http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html
_colors = {
'grey': [247, 8, 7],
'red': [1],
'green': [2],
'yellow': [3],
'brightred': [9, 1],
'brightyellow': [11, 3],
"grey": [247, 8, 7],
"red": [1],
"green": [2],
"yellow": [3],
"brightred": [9, 1],
"brightyellow": [11, 3],
}
fmt = """
{c1}{lineno}{column} {c2}{level}{normal} {message} {c1}{rule}({linter}){normal}
{diff}""".lstrip('\n')
{diff}""".lstrip(
"\n"
)
fmt_summary = "{t.bold}{c}\u2716 {problem} ({error}, {warning}{failure}){t.normal}"
def __init__(self, disable_colors=False):
@ -40,7 +42,7 @@ class StylishFormatter(object):
for num in self._colors[color]:
if num < self.num_colors:
return self.term.color(num)
return ''
return ""
def _reset_max(self):
self.max_lineno = 0
@ -60,15 +62,15 @@ class StylishFormatter(object):
if not diff:
return ""
new_diff = ''
for line in diff.split('\n'):
if line.startswith('+'):
new_diff += self.color('green')
elif line.startswith('-'):
new_diff += self.color('red')
new_diff = ""
for line in diff.split("\n"):
if line.startswith("+"):
new_diff += self.color("green")
elif line.startswith("-"):
new_diff += self.color("red")
else:
new_diff += self.term.normal
new_diff += self._indent_ + line + '\n'
new_diff += self._indent_ + line + "\n"
return new_diff
def __call__(self, result):
@ -85,48 +87,61 @@ class StylishFormatter(object):
for err in errors:
assert isinstance(err, Issue)
self._update_max(err)
if err.level == 'error':
if err.level == "error":
num_errors += 1
else:
num_warnings += 1
for err in sorted(errors, key=lambda e: (int(e.lineno), int(e.column or 0))):
for err in sorted(
errors, key=lambda e: (int(e.lineno), int(e.column or 0))
):
if err.column:
col = ":" + str(err.column).ljust(self.max_column)
else:
col = "".ljust(self.max_column+1)
col = "".ljust(self.max_column + 1)
args = {
'normal': self.term.normal,
'c1': self.color('grey'),
'c2': self.color('red') if err.level == 'error' else self.color('yellow'),
'lineno': str(err.lineno).rjust(self.max_lineno),
'column': col,
'level': err.level.ljust(self.max_level),
'rule': '{} '.format(err.rule) if err.rule else '',
'linter': err.linter.lower(),
'message': err.message.ljust(self.max_message),
'diff': self._get_colored_diff(err.diff).ljust(self.max_message)
"normal": self.term.normal,
"c1": self.color("grey"),
"c2": self.color("red")
if err.level == "error"
else self.color("yellow"),
"lineno": str(err.lineno).rjust(self.max_lineno),
"column": col,
"level": err.level.ljust(self.max_level),
"rule": "{} ".format(err.rule) if err.rule else "",
"linter": err.linter.lower(),
"message": err.message.ljust(self.max_message),
"diff": self._get_colored_diff(err.diff).ljust(self.max_message),
}
message.append(self.fmt.format(**args).rstrip().rstrip('\n'))
message.append(self.fmt.format(**args).rstrip().rstrip("\n"))
message.append('') # newline
message.append("") # newline
# If there were failures, make it clear which linters failed
for fail in failed:
message.append("{c}A failure occurred in the {name} linter.".format(
c=self.color('brightred'),
name=fail,
))
message.append(
"{c}A failure occurred in the {name} linter.".format(
c=self.color("brightred"), name=fail
)
)
# Print a summary
message.append(self.fmt_summary.format(
t=self.term,
c=self.color('brightred') if num_errors or failed else self.color('brightyellow'),
problem=pluralize('problem', num_errors + num_warnings + len(failed)),
error=pluralize('error', num_errors),
warning=pluralize('warning', num_warnings or result.total_suppressed_warnings),
failure=', {}'.format(pluralize('failure', len(failed))) if failed else '',
))
message.append(
self.fmt_summary.format(
t=self.term,
c=self.color("brightred")
if num_errors or failed
else self.color("brightyellow"),
problem=pluralize("problem", num_errors + num_warnings + len(failed)),
error=pluralize("error", num_errors),
warning=pluralize(
"warning", num_warnings or result.total_suppressed_warnings
),
failure=", {}".format(pluralize("failure", len(failed)))
if failed
else "",
)
)
return '\n'.join(message)
return "\n".join(message)

View File

@ -67,28 +67,40 @@ class Issue(object):
"""
__slots__ = (
'linter',
'path',
'message',
'lineno',
'column',
'hint',
'source',
'level',
'rule',
'lineoffset',
'diff'
"linter",
"path",
"message",
"lineno",
"column",
"hint",
"source",
"level",
"rule",
"lineoffset",
"diff",
)
def __init__(self, linter, path, message, lineno, column=None, hint=None,
source=None, level=None, rule=None, lineoffset=None, diff=None):
def __init__(
self,
linter,
path,
message,
lineno,
column=None,
hint=None,
source=None,
level=None,
rule=None,
lineoffset=None,
diff=None,
):
self.path = path
self.message = message
self.lineno = int(lineno) if lineno else 0
self.column = int(column) if column else column
self.hint = hint
self.source = source
self.level = level or 'error'
self.level = level or "error"
self.linter = linter
self.rule = rule
self.lineoffset = lineoffset
@ -127,10 +139,10 @@ def from_config(config, **kwargs):
for attr in Issue.__slots__:
attrs[attr] = kwargs.get(attr, config.get(attr))
if not attrs['linter']:
attrs['linter'] = config.get('name')
if not attrs["linter"]:
attrs["linter"] = config.get("name")
if not attrs['message']:
attrs['message'] = config.get('description')
if not attrs["message"]:
attrs["message"] = config.get("description")
return Issue(**attrs)

View File

@ -15,15 +15,15 @@ from mozlint.result import Issue, ResultSummary
from mozlint import formatters
NORMALISED_PATHS = {
'abc': os.path.normpath('a/b/c.txt'),
'def': os.path.normpath('d/e/f.txt'),
'cwd': mozpath.normpath(os.getcwd()),
"abc": os.path.normpath("a/b/c.txt"),
"def": os.path.normpath("d/e/f.txt"),
"cwd": mozpath.normpath(os.getcwd()),
}
EXPECTED = {
'compact': {
'kwargs': {},
'format': """
"compact": {
"kwargs": {},
"format": """
a/b/c.txt: line 1, Error - oh no foo (foo)
a/b/c.txt: line 4, col 10, Error - oh no baz (baz)
a/b/c.txt: line 5, Error - oh no foo-diff (foo-diff)
@ -32,11 +32,9 @@ d/e/f.txt: line 4, col 2, Warning - oh no bar (bar-not-allowed)
4 problems
""".strip(),
},
'stylish': {
'kwargs': {
'disable_colors': True,
},
'format': """
"stylish": {
"kwargs": {"disable_colors": True},
"format": """
a/b/c.txt
1 error oh no foo (foo)
4:10 error oh no baz (baz)
@ -51,68 +49,67 @@ d/e/f.txt
\u2716 4 problems (3 errors, 1 warning)
""".strip(),
},
'treeherder': {
'kwargs': {},
'format': """
"treeherder": {
"kwargs": {},
"format": """
TEST-UNEXPECTED-ERROR | a/b/c.txt:1 | oh no foo (foo)
TEST-UNEXPECTED-ERROR | a/b/c.txt:4:10 | oh no baz (baz)
TEST-UNEXPECTED-ERROR | a/b/c.txt:5 | oh no foo-diff (foo-diff)
TEST-UNEXPECTED-WARNING | d/e/f.txt:4:2 | oh no bar (bar-not-allowed)
""".strip(),
},
'unix': {
'kwargs': {},
'format': """
"unix": {
"kwargs": {},
"format": """
{abc}:1: foo error: oh no foo
{abc}:4:10: baz error: oh no baz
{abc}:5: foo-diff error: oh no foo-diff
{def}:4:2: bar-not-allowed warning: oh no bar
""".format(**NORMALISED_PATHS).strip(),
""".format(
**NORMALISED_PATHS
).strip(),
},
'summary': {
'kwargs': {},
'format': """
"summary": {
"kwargs": {},
"format": """
{cwd}/a: 3 errors
{cwd}/d: 0 errors, 1 warning
""".format(**NORMALISED_PATHS).strip(),
""".format(
**NORMALISED_PATHS
).strip(),
},
}
@pytest.fixture
def result(scope='module'):
def result(scope="module"):
containers = (
Issue(linter="foo", path="a/b/c.txt", message="oh no foo", lineno=1),
Issue(
linter='foo',
path='a/b/c.txt',
message="oh no foo",
lineno=1,
),
Issue(
linter='bar',
path='d/e/f.txt',
linter="bar",
path="d/e/f.txt",
message="oh no bar",
hint="try baz instead",
level='warning',
level="warning",
lineno="4",
column="2",
rule="bar-not-allowed",
),
Issue(
linter='baz',
path='a/b/c.txt',
linter="baz",
path="a/b/c.txt",
message="oh no baz",
lineno=4,
column=10,
source="if baz:",
),
Issue(
linter='foo-diff',
path='a/b/c.txt',
linter="foo-diff",
path="a/b/c.txt",
message="oh no foo-diff",
lineno=5,
source="if baz:",
diff='diff 1\n- hello\n+ hello2',
diff="diff 1\n- hello\n+ hello2",
),
)
result = ResultSummary()
@ -124,13 +121,13 @@ def result(scope='module'):
@pytest.mark.parametrize("name", EXPECTED.keys())
def test_formatters(result, name):
opts = EXPECTED[name]
fmt = formatters.get(name, **opts['kwargs'])
fmt = formatters.get(name, **opts["kwargs"])
# encoding to str bypasses a UnicodeEncodeError in pytest
assert fmt(result).encode('utf-8') == opts['format'].encode('utf-8')
assert fmt(result).encode("utf-8") == opts["format"].encode("utf-8")
def test_json_formatter(result):
fmt = formatters.get('json')
fmt = formatters.get("json")
formatted = json.loads(fmt(result))
assert set(formatted.keys()) == set(result.issues.keys())
@ -141,5 +138,5 @@ def test_json_formatter(result):
assert all(s in err for s in slots)
if __name__ == '__main__':
if __name__ == "__main__":
mozunit.main()