refactor: use object inheritance for the formaters
This commit is contained in:
@@ -118,7 +118,7 @@ def run(argv=None):
|
|||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
print(e, file=sys.stderr)
|
print(e, file=sys.stderr)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
all_problems[file] = problems
|
all_problems[file] = [pb for pb in problems if pb]
|
||||||
|
|
||||||
if args.stdin:
|
if args.stdin:
|
||||||
# read yaml from stdin
|
# read yaml from stdin
|
||||||
@@ -127,7 +127,7 @@ def run(argv=None):
|
|||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
print(e, file=sys.stderr)
|
print(e, file=sys.stderr)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
all_problems['stdin'] = problems
|
all_problems['stdin'] = [pb for pb in problems if pb]
|
||||||
|
|
||||||
max_level = show_all_problems(
|
max_level = show_all_problems(
|
||||||
all_problems,
|
all_problems,
|
||||||
|
|||||||
@@ -17,46 +17,111 @@ def supports_color():
|
|||||||
hasattr(sys.stdout, 'isatty') and sys.stdout.isatty())
|
hasattr(sys.stdout, 'isatty') and sys.stdout.isatty())
|
||||||
|
|
||||||
|
|
||||||
class Format(object):
|
def run_on_gh():
|
||||||
@staticmethod
|
"""Return if the currnet job is on github."""
|
||||||
def parsable(problem, filename):
|
return 'GITHUB_ACTIONS' in os.environ and 'GITHUB_WORKFLOW' in os.environ
|
||||||
return ('%(file)s:%(line)s:%(column)s: [%(level)s] %(message)s' %
|
|
||||||
{'file': filename,
|
|
||||||
|
class Formater(object):
|
||||||
|
"""Any formater."""
|
||||||
|
# the formater name
|
||||||
|
name = ''
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_formater(cls, name, no_warn):
|
||||||
|
"""Return a formater instance."""
|
||||||
|
|
||||||
|
if name == 'auto':
|
||||||
|
if run_on_gh():
|
||||||
|
name = 'github'
|
||||||
|
elif supports_color():
|
||||||
|
name = 'colored'
|
||||||
|
else:
|
||||||
|
name = 'standard'
|
||||||
|
|
||||||
|
for formater in cls.__subclasses__():
|
||||||
|
if name == formater.name:
|
||||||
|
return formater(no_warn)
|
||||||
|
raise ValueError('unknown formater: %s' % name)
|
||||||
|
|
||||||
|
def __init__(self, no_warn):
|
||||||
|
"""Setup the formater."""
|
||||||
|
self.no_warn = no_warn
|
||||||
|
|
||||||
|
def show_problems_for_all_files(self, all_problems):
|
||||||
|
"""Show all problems of all files."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def show_problems_for_file(self, problems, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def show_problem(self, problem, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
class ParsableFormater(Formater):
|
||||||
|
"""The parsable formater."""
|
||||||
|
name = 'parsable'
|
||||||
|
|
||||||
|
def show_problems_for_all_files(self, all_problems):
|
||||||
|
"""Show all problems of all files."""
|
||||||
|
string = ''
|
||||||
|
for file, problems in all_problems.items():
|
||||||
|
string += self.show_problems_for_file(problems, file)
|
||||||
|
return string
|
||||||
|
|
||||||
|
def show_problems_for_file(self, problems, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
string = ''
|
||||||
|
for problem in problems:
|
||||||
|
string += self.show_problem(problem, file)
|
||||||
|
return string
|
||||||
|
|
||||||
|
def show_problem(self, problem, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
if self.no_warn and (problem.level != 'error'):
|
||||||
|
return ''
|
||||||
|
return (
|
||||||
|
'%(file)s:%(line)s:%(column)s: [%(level)s] %(message)s\n' %
|
||||||
|
{
|
||||||
|
'file': file,
|
||||||
'line': problem.line,
|
'line': problem.line,
|
||||||
'column': problem.column,
|
'column': problem.column,
|
||||||
'level': problem.level,
|
'level': problem.level,
|
||||||
'message': problem.message})
|
'message': problem.message
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def standard(problem, filename):
|
|
||||||
line = ' %d:%d' % (problem.line, problem.column)
|
|
||||||
line += max(12 - len(line), 0) * ' '
|
|
||||||
line += problem.level
|
|
||||||
line += max(21 - len(line), 0) * ' '
|
|
||||||
line += problem.desc
|
|
||||||
if problem.rule:
|
|
||||||
line += ' (%s)' % problem.rule
|
|
||||||
return line
|
|
||||||
|
|
||||||
@staticmethod
|
class GithubFormater(Formater):
|
||||||
def standard_color(problem, filename):
|
"""The parsable formater."""
|
||||||
line = ' \033[2m%d:%d\033[0m' % (problem.line, problem.column)
|
name = 'github'
|
||||||
line += max(20 - len(line), 0) * ' '
|
|
||||||
if problem.level == 'warning':
|
|
||||||
line += '\033[33m%s\033[0m' % problem.level
|
|
||||||
else:
|
|
||||||
line += '\033[31m%s\033[0m' % problem.level
|
|
||||||
line += max(38 - len(line), 0) * ' '
|
|
||||||
line += problem.desc
|
|
||||||
if problem.rule:
|
|
||||||
line += ' \033[2m(%s)\033[0m' % problem.rule
|
|
||||||
return line
|
|
||||||
|
|
||||||
@staticmethod
|
def show_problems_for_all_files(self, all_problems):
|
||||||
def github(problem, filename):
|
"""Show all problems of all files."""
|
||||||
|
string = ''
|
||||||
|
for file, problems in all_problems.items():
|
||||||
|
string += self.show_problems_for_file(problems, file)
|
||||||
|
return string
|
||||||
|
|
||||||
|
def show_problems_for_file(self, problems, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
string = '::group::%s\n' % file
|
||||||
|
for problem in problems:
|
||||||
|
string += self.show_problem(problem, file)
|
||||||
|
if string == '::group::%s\n' % file:
|
||||||
|
return ''
|
||||||
|
return string + '::endgroup::\n\n'
|
||||||
|
|
||||||
|
def show_problem(self, problem, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
if self.no_warn and (problem.level != 'error'):
|
||||||
|
return ''
|
||||||
line = '::'
|
line = '::'
|
||||||
line += problem.level
|
line += problem.level
|
||||||
line += ' file=' + filename + ','
|
line += ' file=' + file + ','
|
||||||
line += 'line=' + format(problem.line) + ','
|
line += 'line=' + format(problem.line) + ','
|
||||||
line += 'col=' + format(problem.column)
|
line += 'col=' + format(problem.column)
|
||||||
line += '::'
|
line += '::'
|
||||||
@@ -67,56 +132,96 @@ class Format(object):
|
|||||||
if problem.rule:
|
if problem.rule:
|
||||||
line += '[' + problem.rule + '] '
|
line += '[' + problem.rule + '] '
|
||||||
line += problem.desc
|
line += problem.desc
|
||||||
|
line += '\n'
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
def show_problems(problems, file, args_format, no_warn):
|
class ColoredFormater(Formater):
|
||||||
first = True
|
"""The parsable formater."""
|
||||||
|
name = 'colored'
|
||||||
|
|
||||||
if args_format == 'auto':
|
def show_problems_for_all_files(self, all_problems):
|
||||||
if ('GITHUB_ACTIONS' in os.environ and
|
"""Show all problems of all files."""
|
||||||
'GITHUB_WORKFLOW' in os.environ):
|
string = ''
|
||||||
args_format = 'github'
|
for file, problems in all_problems.items():
|
||||||
elif supports_color():
|
string += self.show_problems_for_file(problems, file)
|
||||||
args_format = 'colored'
|
return string
|
||||||
|
|
||||||
|
def show_problems_for_file(self, problems, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
string = '\033[4m%s\033[0m\n' % file
|
||||||
for problem in problems:
|
for problem in problems:
|
||||||
if no_warn and (problem.level != 'error'):
|
string += self.show_problem(problem, file)
|
||||||
continue
|
if string == '\033[4m%s\033[0m\n' % file:
|
||||||
if args_format == 'parsable':
|
return ''
|
||||||
print(Format.parsable(problem, file))
|
return string + '\n'
|
||||||
elif args_format == 'github':
|
|
||||||
if first:
|
def show_problem(self, problem, file):
|
||||||
print('::group::%s' % file)
|
"""Show all problems of a specific file."""
|
||||||
first = False
|
if self.no_warn and (problem.level != 'error'):
|
||||||
print(Format.github(problem, file))
|
return ''
|
||||||
elif args_format == 'colored':
|
line = ' \033[2m%d:%d\033[0m' % (problem.line, problem.column)
|
||||||
if first:
|
line += max(20 - len(line), 0) * ' '
|
||||||
print('\033[4m%s\033[0m' % file)
|
if problem.level == 'warning':
|
||||||
first = False
|
line += '\033[33m%s\033[0m' % problem.level
|
||||||
print(Format.standard_color(problem, file))
|
|
||||||
else:
|
else:
|
||||||
if first:
|
line += '\033[31m%s\033[0m' % problem.level
|
||||||
print(file)
|
line += max(38 - len(line), 0) * ' '
|
||||||
first = False
|
line += problem.desc
|
||||||
print(Format.standard(problem, file))
|
if problem.rule:
|
||||||
|
line += ' \033[2m(%s)\033[0m' % problem.rule
|
||||||
if not first and args_format == 'github':
|
line += '\n'
|
||||||
print('::endgroup::')
|
return line
|
||||||
|
|
||||||
if not first and args_format != 'parsable':
|
|
||||||
print('')
|
|
||||||
|
|
||||||
|
|
||||||
def max_level(problems):
|
class StandardFormater(Formater):
|
||||||
|
"""The parsable formater."""
|
||||||
|
name = 'standard'
|
||||||
|
|
||||||
|
def show_problems_for_all_files(self, all_problems):
|
||||||
|
"""Show all problems of all files."""
|
||||||
|
string = ''
|
||||||
|
for file, problems in all_problems.items():
|
||||||
|
string += self.show_problems_for_file(problems, file)
|
||||||
|
return string
|
||||||
|
|
||||||
|
def show_problems_for_file(self, problems, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
string = file + '\n'
|
||||||
|
for problem in problems:
|
||||||
|
string += self.show_problem(problem, file)
|
||||||
|
if string == file + '\n':
|
||||||
|
return ''
|
||||||
|
return string + '\n'
|
||||||
|
|
||||||
|
def show_problem(self, problem, file):
|
||||||
|
"""Show all problems of a specific file."""
|
||||||
|
if self.no_warn and (problem.level != 'error'):
|
||||||
|
return ''
|
||||||
|
line = ' %d:%d' % (problem.line, problem.column)
|
||||||
|
line += max(12 - len(line), 0) * ' '
|
||||||
|
line += problem.level
|
||||||
|
line += max(21 - len(line), 0) * ' '
|
||||||
|
line += problem.desc
|
||||||
|
if problem.rule:
|
||||||
|
line += ' (%s)' % problem.rule
|
||||||
|
line += '\n'
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
def max_level(all_problems):
|
||||||
"""Return the max level of all problems."""
|
"""Return the max level of all problems."""
|
||||||
return max(PROBLEM_LEVELS[problem.level] for problem in problems)
|
all_levels = [problem.level for problems in all_problems.values() for problem in problems]
|
||||||
|
if all_levels:
|
||||||
|
return max(map(lambda x: PROBLEM_LEVELS[x], all_levels))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def show_all_problems(all_problems, args_format, no_warn):
|
def show_all_problems(all_problems, args_format, no_warn):
|
||||||
"""Print all problems, return the max level."""
|
"""Print all problems, return the max level."""
|
||||||
|
|
||||||
for file, problem in all_problems.items():
|
fmt = Formater.get_formater(args_format, no_warn)
|
||||||
show_problems(problem, file, args_format, no_warn)
|
|
||||||
|
print(fmt.show_problems_for_all_files(all_problems), end='')
|
||||||
|
|
||||||
return max_level(all_problems)
|
return max_level(all_problems)
|
||||||
|
|||||||
Reference in New Issue
Block a user