diff --git a/src/pricehist/cli.py b/src/pricehist/cli.py index 1ae3d6a..8cbf9b3 100644 --- a/src/pricehist/cli.py +++ b/src/pricehist/cli.py @@ -97,6 +97,13 @@ def build_parser(): def today(): return datetime.now().date().isoformat() + def valid_char(s): + if len(s) == 1: + return s + else: + msg = f"Not a single character: '{s}'." + raise argparse.ArgumentTypeError(msg) + def formatter(prog): return argparse.HelpFormatter(prog, max_help_position=50) @@ -164,7 +171,8 @@ def build_parser(): "[--invert] [--quantize INT] " "[--fmt-base SYM] [--fmt-quote SYM] [--fmt-time TIME] " "[--fmt-decimal CHAR] [--fmt-thousands CHAR] " - "[--fmt-symbol rightspace|right|leftspace|left] [--fmt-datesep CHAR]" + "[--fmt-symbol rightspace|right|leftspace|left] [--fmt-datesep CHAR] " + "[--fmt-csvdelim CHAR]" ), formatter_class=formatter, ) @@ -299,5 +307,12 @@ def build_parser(): type=str, help=f"date separator in output (default: '{default_fmt.datesep}')", ) + fetch_parser.add_argument( + "--fmt-csvdelim", + dest="formatcsvdelim", + metavar="CHAR", + type=valid_char, + help=f"field delimiter for CSV output (default: '{default_fmt.csvdelim}')", + ) return parser diff --git a/src/pricehist/format.py b/src/pricehist/format.py index 7513f71..fb7a8de 100644 --- a/src/pricehist/format.py +++ b/src/pricehist/format.py @@ -10,6 +10,7 @@ class Format: thousands: str = "" symbol: str = "rightspace" datesep: str = "-" + csvdelim: str = "," @classmethod def fromargs(cls, args): @@ -25,6 +26,7 @@ class Format: thousands=if_not_none(args.formatthousands, default.thousands), symbol=if_not_none(args.formatsymbol, default.symbol), datesep=if_not_none(args.formatdatesep, default.datesep), + csvdelim=if_not_none(args.formatcsvdelim, default.csvdelim), ) def format_date(self, date): diff --git a/src/pricehist/outputs/csv.py b/src/pricehist/outputs/csv.py index 81cfc02..ec44b93 100644 --- a/src/pricehist/outputs/csv.py +++ b/src/pricehist/outputs/csv.py @@ -1,16 +1,32 @@ -from pricehist.format import Format +import csv +import io +from pricehist.format import Format from .baseoutput import BaseOutput class CSV(BaseOutput): def format(self, series, source=None, fmt=Format()): - lines = ["date,base,quote,amount,source,type"] + output = io.StringIO() + writer = csv.writer( + output, + delimiter=fmt.csvdelim, + lineterminator="\n", + quotechar='"', + doublequote=True, + skipinitialspace=False, + quoting=csv.QUOTE_MINIMAL, + ) + + header = ["date", "base", "quote", "amount", "source", "type"] + writer.writerow(header) + + base = fmt.base or series.base + quote = fmt.quote or series.quote + for price in series.prices: date = fmt.format_date(price.date) - base = fmt.base or series.base - quote = fmt.quote or series.quote amount = fmt.format_num(price.amount) - line = ",".join([date, base, quote, amount, source.id(), series.type]) - lines.append(line) - return "\n".join(lines) + "\n" + writer.writerow([date, base, quote, amount, source.id(), series.type]) + + return output.getvalue()