Now information messages go to stdout (not stderr).

Debug, warning and error messages still use stderr.
This commit is contained in:
Salvador E. Tropea 2021-01-22 17:17:41 -03:00
parent eba8da098d
commit 86b1c13790
7 changed files with 66 additions and 42 deletions

View File

@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
This status was moved to a separated column named `Status`. This status was moved to a separated column named `Status`.
You can join both columns if you want. You can join both columns if you want.
- Internal BoM: HTML rows are highlighted on hover (not just the cell). - Internal BoM: HTML rows are highlighted on hover (not just the cell).
- Now information messages go to stdout (not stderr).
Debug, warning and error messages still use stderr.
### Fixed ### Fixed
- Extra data about drill marks in gerber files. - Extra data about drill marks in gerber files.

View File

@ -99,13 +99,33 @@ def set_verbosity(logger, verbose, quiet):
logger.setLevel(log_level) logger.setLevel(log_level)
class FilterOnlyInfo(object):
def filter(self, record):
return record.levelno == logging.INFO
class FilterNoInfo(object):
def filter(self, record):
return record.levelno != logging.INFO
def init(): def init():
"""Initialize the logging feature using a custom format""" """Initialize the logging feature using a custom format"""
# Use a class to count and filter warnings # Use a class to count and filter warnings
logging.setLoggerClass(MyLogger) logging.setLoggerClass(MyLogger)
logger = get_logger() logger = get_logger()
# Handler for all but info.
# Outputs to stderr
ch = logging.StreamHandler() ch = logging.StreamHandler()
ch.setFormatter(CustomFormatter()) ch.addFilter(FilterNoInfo())
ch.setFormatter(CustomFormatter(sys.stderr))
logger.addHandler(ch)
# Handler for t info.
# Outputs to stdout
ch = logging.StreamHandler()
ch.setStream(sys.stdout)
ch.addFilter(FilterOnlyInfo())
ch.setFormatter(CustomFormatter(sys.stdout))
logger.addHandler(ch) logger.addHandler(ch)
return logger return logger
@ -113,32 +133,34 @@ def init():
class CustomFormatter(logging.Formatter): class CustomFormatter(logging.Formatter):
"""Logging Formatter to add colors""" """Logging Formatter to add colors"""
if sys.stderr.isatty(): def __init__(self, stream):
white = Fore.WHITE super().__init__()
yellow = Fore.YELLOW + Style.BRIGHT if stream.isatty():
red = Fore.RED + Style.BRIGHT white = Fore.WHITE
red_alarm = Fore.RED + Back.WHITE + Style.BRIGHT yellow = Fore.YELLOW + Style.BRIGHT
cyan = Fore.CYAN + Style.BRIGHT red = Fore.RED + Style.BRIGHT
reset = Style.RESET_ALL red_alarm = Fore.RED + Back.WHITE + Style.BRIGHT
else: cyan = Fore.CYAN + Style.BRIGHT
white = "" reset = Style.RESET_ALL
yellow = "" else:
red = "" white = ""
red_alarm = "" yellow = ""
cyan = "" red = ""
reset = "" red_alarm = ""
# format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s " cyan = ""
# "(%(filename)s:%(lineno)d)" reset = ""
format = "%(levelname)s:%(message)s (%(name)s - %(filename)s:%(lineno)d)" # format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s "
format_simple = "%(message)s" # "(%(filename)s:%(lineno)d)"
format = "%(levelname)s:%(message)s (%(name)s - %(filename)s:%(lineno)d)"
format_simple = "%(message)s"
FORMATS = { self.FORMATS = {
logging.DEBUG: cyan + format + reset, logging.DEBUG: cyan + format + reset,
logging.INFO: white + format_simple + reset, logging.INFO: white + format_simple + reset,
logging.WARNING: yellow + format + reset, logging.WARNING: yellow + format + reset,
logging.ERROR: red + format + reset, logging.ERROR: red + format + reset,
logging.CRITICAL: red_alarm + format + reset logging.CRITICAL: red_alarm + format + reset
} }
def format(self, record): def format(self, record):
log_fmt = self.FORMATS.get(record.levelno) log_fmt = self.FORMATS.get(record.levelno)

View File

@ -52,7 +52,7 @@ def check_modules(ctx, fname, expected):
logging.debug("List of components OK") logging.debug("List of components OK")
def test_ibom(): def test_ibom_1():
prj = 'bom' prj = 'bom'
ctx = context.TestContext('BoM_interactive', prj, 'ibom', BOM_DIR) ctx = context.TestContext('BoM_interactive', prj, 'ibom', BOM_DIR)
ctx.run() ctx.run()

View File

@ -1411,7 +1411,7 @@ def test_int_bom_variant_cl_gl():
prj = 'kibom-variante' prj = 'kibom-variante'
ctx = context.TestContextSCH('test_int_bom_variant_cl_gl', prj, 'int_bom_var_t1_glb', BOM_DIR) ctx = context.TestContextSCH('test_int_bom_variant_cl_gl', prj, 'int_bom_var_t1_glb', BOM_DIR)
ctx.run(extra=['--global-redef', 'variant=t1_v2']) ctx.run(extra=['--global-redef', 'variant=t1_v2'])
ctx.search_err(r'Using command line value .?t1_v2.? for global option .?variant.?') ctx.search_out(r'Using command line value .?t1_v2.? for global option .?variant.?')
# No variant -> t1_v2 # No variant -> t1_v2
logging.debug("* No variant -> t1_v2") logging.debug("* No variant -> t1_v2")
rows, header, info = ctx.load_csv(prj+'-bom_(V2).csv') rows, header, info = ctx.load_csv(prj+'-bom_(V2).csv')

View File

@ -203,8 +203,8 @@ def test_auto_pcb_and_cfg():
ctx.dont_expect_out_file(ctx.get_pos_both_filename()) ctx.dont_expect_out_file(ctx.get_pos_both_filename())
ctx.expect_out_file(ctx.get_pos_both_csv_filename()) ctx.expect_out_file(ctx.get_pos_both_csv_filename())
assert ctx.search_err('Using PCB file: '+board_file) assert ctx.search_out('Using PCB file: '+board_file)
assert ctx.search_err('Using config file: '+yaml_file) assert ctx.search_out('Using config file: '+yaml_file)
ctx.clean_up() ctx.clean_up()
@ -249,8 +249,8 @@ def test_auto_pcb_and_cfg_3():
ctx.run(extra=['-s', 'all', '-i'], no_out_dir=True, no_board_file=True, no_yaml_file=True, chdir_out=True) ctx.run(extra=['-s', 'all', '-i'], no_out_dir=True, no_board_file=True, no_yaml_file=True, chdir_out=True)
assert ctx.search_err('Using SCH file: '+sch) assert ctx.search_out('Using SCH file: '+sch)
assert ctx.search_err('Using config file: '+yaml_file) assert ctx.search_out('Using config file: '+yaml_file)
ctx.clean_up() ctx.clean_up()
@ -273,7 +273,7 @@ def test_auto_pcb_and_cfg_4():
ctx.run(extra=['-s', 'all', '-i'], no_out_dir=True, no_board_file=True, no_yaml_file=True, chdir_out=True) ctx.run(extra=['-s', 'all', '-i'], no_out_dir=True, no_board_file=True, no_yaml_file=True, chdir_out=True)
assert ctx.search_err('Using '+sch) assert ctx.search_err('Using '+sch)
assert ctx.search_err('Using config file: '+yaml_file) assert ctx.search_out('Using config file: '+yaml_file)
ctx.clean_up() ctx.clean_up()
@ -293,7 +293,7 @@ def test_auto_pcb_and_cfg_5():
ctx.run(extra=['-s', 'all', '-i'], no_out_dir=True, no_board_file=True, no_yaml_file=True, chdir_out=True) ctx.run(extra=['-s', 'all', '-i'], no_out_dir=True, no_board_file=True, no_yaml_file=True, chdir_out=True)
assert ctx.search_err('Using (b_)?'+sch) assert ctx.search_err('Using (b_)?'+sch)
assert ctx.search_err('Using config file: '+yaml_file) assert ctx.search_out('Using config file: '+yaml_file)
ctx.clean_up() ctx.clean_up()
@ -302,11 +302,11 @@ def test_list():
ctx = context.TestContext('List', '3Rs', 'pre_and_position', POS_DIR) ctx = context.TestContext('List', '3Rs', 'pre_and_position', POS_DIR)
ctx.run(extra=['--list'], no_verbose=True, no_out_dir=True, no_board_file=True) ctx.run(extra=['--list'], no_verbose=True, no_out_dir=True, no_board_file=True)
assert ctx.search_err('run_erc: True') assert ctx.search_out('run_erc: True')
assert ctx.search_err('run_drc: True') assert ctx.search_out('run_drc: True')
assert ctx.search_err('update_xml: True') assert ctx.search_out('update_xml: True')
assert ctx.search_err(r'Pick and place file.? \(position\) \[position\]') assert ctx.search_out(r'Pick and place file.? \(position\) \[position\]')
assert ctx.search_err(r'Pick and place file.? \(pos_ascii\) \[position\]') assert ctx.search_out(r'Pick and place file.? \(pos_ascii\) \[position\]')
ctx.clean_up() ctx.clean_up()

View File

@ -142,7 +142,7 @@ def test_sch_missing_1():
ctx.search_err("Component .?Resistor.? doesn't specify its library") ctx.search_err("Component .?Resistor.? doesn't specify its library")
ctx.search_err("Missing component .?l1:FooBar.?") ctx.search_err("Missing component .?l1:FooBar.?")
ctx.search_err("Missing component(.*)Resistor", invert=True) ctx.search_err("Missing component(.*)Resistor", invert=True)
ctx.search_err(r"Found 3 unique warning/s \(4 total\)") ctx.search_out(r"Found 3 unique warning/s \(4 total\)")
ctx.clean_up() ctx.clean_up()
@ -157,7 +157,7 @@ def test_sch_missing_filtered():
ctx.search_err("Component .?Resistor.? doesn't specify its library") ctx.search_err("Component .?Resistor.? doesn't specify its library")
ctx.search_err("Missing component .?l1:FooBar.?", invert=True) ctx.search_err("Missing component .?l1:FooBar.?", invert=True)
ctx.search_err("Missing component(.*)Resistor", invert=True) ctx.search_err("Missing component(.*)Resistor", invert=True)
ctx.search_err(r"Found 2 unique warning/s \(4 total, 2 filtered\)") ctx.search_out(r"Found 2 unique warning/s \(4 total, 2 filtered\)")
ctx.clean_up() ctx.clean_up()

View File

@ -200,7 +200,7 @@ def test_svg_anchor():
ctx = context.TestContext('test_svg_anchor', prj, 'svg_anchor', PS_DIR) ctx = context.TestContext('test_svg_anchor', prj, 'svg_anchor', PS_DIR)
ctx.run(extra=['SVG']) ctx.run(extra=['SVG'])
assert ctx.search_err(r"- 'SVG files' \(SVG\) \[svg\]") assert ctx.search_out(r"- 'SVG files' \(SVG\) \[svg\]")
ctx.expect_out_file(ctx.get_gerber_filename('B_Cu', '.svg')) ctx.expect_out_file(ctx.get_gerber_filename('B_Cu', '.svg'))
ctx.expect_out_file(ctx.get_gerber_filename('F_Cu', '.svg')) ctx.expect_out_file(ctx.get_gerber_filename('F_Cu', '.svg'))
ctx.expect_out_file(ctx.get_gerber_filename('GND_Cu', '.svg')) ctx.expect_out_file(ctx.get_gerber_filename('GND_Cu', '.svg'))