CLI colors refactored
Colors are now stored in their own module. Output coloring was factored out into a separate utility function. State => color mapping is now implemented as a dictionary instead of multiple conditionals. Tests included. Signed-off-by: Jiri Podivin <jpodivin@redhat.com> Change-Id: I41f15c28dfddd911294ecc8e3e0331a4956dc5d8
This commit is contained in:
parent
5fad1a4d18
commit
03981dba8a
57
validations_libs/cli/colors.py
Normal file
57
validations_libs/cli/colors.py
Normal file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2021 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# PrettyTable Colors:
|
||||
RED = "\033[1;31m"
|
||||
GREEN = "\033[0;32m"
|
||||
CYAN = "\033[36m"
|
||||
RESET = "\033[0;0m"
|
||||
YELLOW = "\033[0;33m"
|
||||
|
||||
colors = {
|
||||
'starting': CYAN,
|
||||
'running': CYAN,
|
||||
'PASSED': GREEN,
|
||||
'UNKNOWN': YELLOW,
|
||||
'UNREACHABLE': YELLOW,
|
||||
'ERROR': RED,
|
||||
'FAILED': RED
|
||||
}
|
||||
|
||||
|
||||
def color_output(output, status=None):
|
||||
"""Apply color to output based on colors dict entries.
|
||||
Unknown status or no status at all results in aplication
|
||||
of YELLOW color.
|
||||
|
||||
.. note::
|
||||
|
||||
Coloring itself is performed using format method of the
|
||||
string class. This function is merely a wrapper around it,
|
||||
and around ANSI escape sequences as defined by ECMA-48.
|
||||
|
||||
"""
|
||||
if status:
|
||||
color = colors.get(status, YELLOW)
|
||||
else:
|
||||
color = colors['UNKNOWN']
|
||||
|
||||
output = '{}{}{}'.format(
|
||||
color,
|
||||
output,
|
||||
RESET)
|
||||
|
||||
return output
|
@ -19,16 +19,10 @@ from prettytable import PrettyTable
|
||||
|
||||
from validations_libs import constants
|
||||
from validations_libs import utils as v_utils
|
||||
from validations_libs.cli import colors
|
||||
|
||||
GROUP_FILE = constants.VALIDATION_GROUPS_INFO
|
||||
|
||||
# PrettyTable Colors:
|
||||
RED = "\033[1;31m"
|
||||
GREEN = "\033[0;32m"
|
||||
CYAN = "\033[36m"
|
||||
RESET = "\033[0;0m"
|
||||
YELLOW = "\033[0;33m"
|
||||
|
||||
|
||||
def print_dict(data):
|
||||
"""Print table from python dict with PrettyTable"""
|
||||
@ -49,16 +43,12 @@ def print_dict(data):
|
||||
# if ValueError, then host is in unknown state:
|
||||
_name = host
|
||||
_status = 'UNKNOWN'
|
||||
color = (GREEN if _status == 'PASSED' else
|
||||
(YELLOW if _status == 'UNREACHABLE' else RED))
|
||||
_name = '{}{}{}'.format(color, _name, RESET)
|
||||
_name = colors.color_output(_name, status=_status)
|
||||
hosts.append(_name)
|
||||
row['Status_by_Host'] = ', '.join(hosts)
|
||||
if row.get('Status'):
|
||||
status = row.get('Status')
|
||||
color = (CYAN if status in ['starting', 'running']
|
||||
else GREEN if status == 'PASSED' else RED)
|
||||
row['Status'] = '{}{}{}'.format(color, status, RESET)
|
||||
row['Status'] = colors.color_output(status, status=status)
|
||||
table.add_row(row.values())
|
||||
print(table)
|
||||
|
||||
|
68
validations_libs/tests/cli/test_colors.py
Normal file
68
validations_libs/tests/cli/test_colors.py
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright 2021 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
try:
|
||||
from unittest import mock
|
||||
except ImportError:
|
||||
import mock
|
||||
from unittest import TestCase
|
||||
|
||||
from validations_libs.cli import colors
|
||||
|
||||
|
||||
class TestColors(TestCase):
|
||||
def setUp(self):
|
||||
RED = "\033[1;31m"
|
||||
GREEN = "\033[0;32m"
|
||||
CYAN = "\033[36m"
|
||||
RESET = "\033[0;0m"
|
||||
YELLOW = "\033[0;33m"
|
||||
|
||||
self.status_color = {
|
||||
'starting': CYAN,
|
||||
'running': CYAN,
|
||||
'PASSED': GREEN,
|
||||
'UNKNOWN': YELLOW,
|
||||
'UNREACHABLE': YELLOW,
|
||||
'ERROR': RED,
|
||||
'FAILED': RED
|
||||
}
|
||||
|
||||
super(TestColors, self).setUp()
|
||||
|
||||
def test_format_known_status(self):
|
||||
"""Tests formatting, meaning coloring, for every
|
||||
status recognized by VF.
|
||||
"""
|
||||
|
||||
for status in self.status_color:
|
||||
color = self.status_color[status]
|
||||
colored_output = colors.color_output("fizz", status=status)
|
||||
#Checking reset color
|
||||
self.assertEquals(colored_output[-6:], '\033[0;0m')
|
||||
#Checking output color
|
||||
self.assertEquals(colored_output[:len(color)], color)
|
||||
#Checking output string
|
||||
self.assertEquals(colored_output[len(color):][:4], "fizz")
|
||||
|
||||
def test_format_unknown_status(self):
|
||||
|
||||
color = self.status_color['UNKNOWN']
|
||||
colored_output = colors.color_output("buzz")
|
||||
#Checking reset color
|
||||
self.assertEquals(colored_output[-6:], '\033[0;0m')
|
||||
#Checking output color
|
||||
self.assertEquals(colored_output[:len(color)], color)
|
||||
#Checking output string
|
||||
self.assertEquals(colored_output[len(color):][:4], "buzz")
|
Loading…
x
Reference in New Issue
Block a user