Don't print directly to stdout.

This commit is contained in:
Chris Berkhout 2021-05-27 20:00:29 +02:00
parent 59a17a9896
commit 9c64767ed1

View file

@ -1,6 +1,7 @@
import argparse import argparse
import logging import logging
import shutil import shutil
import sys
from datetime import datetime, timedelta from datetime import datetime, timedelta
from textwrap import TextWrapper from textwrap import TextWrapper
@ -9,7 +10,7 @@ from pricehist.format import Format
from pricehist.series import Series from pricehist.series import Series
def cli(args=None): def cli(args=None, output_file=sys.stdout):
start_time = datetime.now() start_time = datetime.now()
logging.basicConfig(format="%(message)s", level=logging.INFO) logging.basicConfig(format="%(message)s", level=logging.INFO)
@ -23,37 +24,39 @@ def cli(args=None):
logging.debug(f"Started pricehist run at {start_time}.") logging.debug(f"Started pricehist run at {start_time}.")
try:
if args.version: if args.version:
cmd_version() print(f"pricehist v{__version__}", file=output_file)
elif args.command == "sources": elif args.command == "sources":
cmd_sources(args) print(cmd_sources(args), file=output_file)
elif args.command == "source": elif args.command == "source":
cmd_source(args) print(cmd_source(args), file=output_file)
elif args.command == "fetch": elif args.command == "fetch":
cmd_fetch(args) print(cmd_fetch(args), end="", file=output_file)
else: else:
parser.print_help() parser.print_help(file=output_file)
except BrokenPipeError:
logging.debug("The output pipe was closed early.")
logging.debug(f"Finished pricehist run at {datetime.now()}.") logging.debug(f"Finished pricehist run at {datetime.now()}.")
def cmd_version():
print(f"pricehist v{__version__}")
def cmd_sources(args): def cmd_sources(args):
width = max([len(identifier) for identifier in sources.by_id.keys()]) width = max([len(identifier) for identifier in sources.by_id.keys()])
for identifier, source in sources.by_id.items(): source_lines = [
print(f"{identifier.ljust(width)} {source.name()}") f"{identifier.ljust(width)} {source.name()}"
for identifier, source in sources.by_id.items()
]
return "\n".join(source_lines)
def cmd_source(args): def cmd_source(args):
def print_field(key, value, key_width, output_width, force=True): def fmt_field(key, value, key_width, total_width, force=True):
separator = " : " separator = " : "
initial_indent = key + (" " * (key_width - len(key))) + separator initial_indent = key + (" " * (key_width - len(key))) + separator
subsequent_indent = " " * len(initial_indent) subsequent_indent = " " * len(initial_indent)
wrapper = TextWrapper( wrapper = TextWrapper(
width=output_width, width=total_width,
drop_whitespace=True, drop_whitespace=True,
initial_indent=initial_indent, initial_indent=initial_indent,
subsequent_indent=subsequent_indent, subsequent_indent=subsequent_indent,
@ -65,28 +68,31 @@ def cmd_source(args):
rest_output = sum([wrapper.wrap(line) if line else ["\n"] for line in rest], []) rest_output = sum([wrapper.wrap(line) if line else ["\n"] for line in rest], [])
output = "\n".join(first_output + rest_output) output = "\n".join(first_output + rest_output)
if output != "": if output != "":
print(output) return output
else:
return None
source = sources.by_id[args.identifier] source = sources.by_id[args.identifier]
if args.symbols: if args.symbols:
print("\n".join(source.symbols())) return "\n".join(source.symbols())
else: else:
key_width = 11 k_width = 11
output_width = shutil.get_terminal_size().columns total_width = shutil.get_terminal_size().columns
parts = [
print_field("ID", source.id(), key_width, output_width) fmt_field("ID", source.id(), k_width, total_width),
print_field("Name", source.name(), key_width, output_width) fmt_field("Name", source.name(), k_width, total_width),
print_field("Description", source.description(), key_width, output_width) fmt_field("Description", source.description(), k_width, total_width),
print_field("URL", source.source_url(), key_width, output_width, force=False) fmt_field("URL", source.source_url(), k_width, total_width, force=False),
print_field("Start", source.start(), key_width, output_width) fmt_field("Start", source.start(), k_width, total_width),
print_field("Types", ", ".join(source.types()), key_width, output_width) fmt_field("Types", ", ".join(source.types()), k_width, total_width),
print_field("Notes", source.notes(), key_width, output_width) fmt_field("Notes", source.notes(), k_width, total_width),
]
return "\n".join(filter(None, parts))
def cmd_fetch(args): def cmd_fetch(args):
source = sources.by_id[args.source] source = sources.by_id[args.source]
output = outputs.by_type[args.output]
start = args.start or source.start() start = args.start or source.start()
type = args.type or (source.types() + ["unknown"])[0] type = args.type or (source.types() + ["unknown"])[0]
@ -108,11 +114,10 @@ def cmd_fetch(args):
if args.renamequote: if args.renamequote:
series = series.rename_quote(args.renamequote) series = series.rename_quote(args.renamequote)
default = Format()
def if_not_none(value, default): def if_not_none(value, default):
return default if value is None else value return default if value is None else value
default = Format()
fmt = Format( fmt = Format(
time=if_not_none(args.renametime, default.time), time=if_not_none(args.renametime, default.time),
decimal=if_not_none(args.formatdecimal, default.decimal), decimal=if_not_none(args.formatdecimal, default.decimal),
@ -121,10 +126,8 @@ def cmd_fetch(args):
datesep=if_not_none(args.formatdatesep, default.datesep), datesep=if_not_none(args.formatdatesep, default.datesep),
) )
try: output = outputs.by_type[args.output]
print(output.format(series, source, fmt=fmt), end="") return output.format(series, source, fmt=fmt)
except BrokenPipeError:
logging.debug("The output pipe was closed early.")
def build_parser(): def build_parser():