From dd724b6c287c089587ae9e79a1148e2cbb78a800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Murta?= Date: Thu, 23 Feb 2023 23:21:54 +0000 Subject: [PATCH] Export in .csv Importing is not supported, since there's no way to represent a Null field in .csv --- pfbudget/__main__.py | 4 +-- pfbudget/cli/argparser.py | 25 ++++++++++--------- pfbudget/core/manager.py | 51 +++++++++++++++++++++++++-------------- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/pfbudget/__main__.py b/pfbudget/__main__.py index 98fcb65..7a28ef5 100644 --- a/pfbudget/__main__.py +++ b/pfbudget/__main__.py @@ -253,9 +253,9 @@ if __name__ == "__main__": | Operation.ExportCategoryGroups | Operation.ImportCategoryGroups ): - keys = {"file"} + keys = {"file", "format"} assert args.keys() >= keys, f"missing {args.keys() - keys}" - params = args["file"] + params = [args["file"][0], args["format"][0]] Manager(db, verbosity).action(op, params) diff --git a/pfbudget/cli/argparser.py b/pfbudget/cli/argparser.py index 1e47aa6..298aa04 100644 --- a/pfbudget/cli/argparser.py +++ b/pfbudget/cli/argparser.py @@ -63,7 +63,7 @@ def argparser() -> argparse.ArgumentParser: # Exports transactions to .csv file export = subparsers.add_parser("export") export.set_defaults(op=Operation.Export) - export_args(export) + file_options(export) pimport = subparsers.add_parser("import") pimport.set_defaults(op=Operation.Import) @@ -215,11 +215,11 @@ def bank(parser: argparse.ArgumentParser): export = commands.add_parser("export") export.set_defaults(op=Operation.ExportBanks) - export_args(export) + file_options(export) pimport = commands.add_parser("import") pimport.set_defaults(op=Operation.ImportBanks) - export_args(pimport) + file_options(pimport) def nordigen(parser: argparse.ArgumentParser): @@ -276,11 +276,11 @@ def category(parser: argparse.ArgumentParser): export = commands.add_parser("export") export.set_defaults(op=Operation.ExportCategories) - export_args(export) + file_options(export) pimport = commands.add_parser("import") pimport.set_defaults(op=Operation.ImportCategories) - export_args(pimport) + file_options(pimport) def category_group(parser: argparse.ArgumentParser): @@ -296,11 +296,11 @@ def category_group(parser: argparse.ArgumentParser): export = commands.add_parser("export") export.set_defaults(op=Operation.ExportCategoryGroups) - export_args(export) + file_options(export) pimport = commands.add_parser("import") pimport.set_defaults(op=Operation.ImportCategoryGroups) - export_args(pimport) + file_options(pimport) def category_rule(parser: argparse.ArgumentParser): @@ -324,11 +324,11 @@ def category_rule(parser: argparse.ArgumentParser): export = commands.add_parser("export") export.set_defaults(op=Operation.ExportCategoryRules) - export_args(export) + file_options(export) pimport = commands.add_parser("import") pimport.set_defaults(op=Operation.ImportCategoryRules) - export_args(pimport) + file_options(pimport) def tags(parser: argparse.ArgumentParser): @@ -366,11 +366,11 @@ def tag_rule(parser: argparse.ArgumentParser): export = commands.add_parser("export") export.set_defaults(op=Operation.ExportTagRules) - export_args(export) + file_options(export) pimport = commands.add_parser("import") pimport.set_defaults(op=Operation.ImportTagRules) - export_args(pimport) + file_options(pimport) def rules(parser: argparse.ArgumentParser): @@ -397,5 +397,6 @@ def link(parser: argparse.ArgumentParser): dismantle.add_argument("links", nargs="+", type=int) -def export_args(parser: argparse.ArgumentParser): +def file_options(parser: argparse.ArgumentParser): parser.add_argument("file", nargs=1, type=str) + parser.add_argument("format", nargs=1, default="pickle") diff --git a/pfbudget/core/manager.py b/pfbudget/core/manager.py index 27df90b..227a8f4 100644 --- a/pfbudget/core/manager.py +++ b/pfbudget/core/manager.py @@ -1,3 +1,4 @@ +import csv from pathlib import Path import pickle import webbrowser @@ -241,11 +242,11 @@ class Manager: case Operation.Export: with self.db.session() as session: - self.dump(params[0], sorted(session.get(Transaction))) + self.dump(params[0], params[1], sorted(session.get(Transaction))) case Operation.Import: transactions = [] - for row in self.load(params[0]): + for row in self.load(params[0], params[1]): match row["type"]: case "bank": transaction = BankTransaction( @@ -278,11 +279,11 @@ class Manager: case Operation.ExportBanks: with self.db.session() as session: - self.dump(params[0], session.get(Bank)) + self.dump(params[0], params[1], session.get(Bank)) case Operation.ImportBanks: banks = [] - for row in self.load(params[0]): + for row in self.load(params[0], params[1]): bank = Bank(row["name"], row["BIC"], row["type"]) if row["nordigen"]: bank.nordigen = Nordigen(**row["nordigen"]) @@ -294,10 +295,10 @@ class Manager: case Operation.ExportCategoryRules: with self.db.session() as session: - self.dump(params[0], session.get(CategoryRule)) + self.dump(params[0], params[1], session.get(CategoryRule)) case Operation.ImportCategoryRules: - rules = [CategoryRule(**row) for row in self.load(params[0])] + rules = [CategoryRule(**row) for row in self.load(params[0], params[1])] if self.certify(rules): with self.db.session() as session: @@ -305,10 +306,10 @@ class Manager: case Operation.ExportTagRules: with self.db.session() as session: - self.dump(params[0], session.get(TagRule)) + self.dump(params[0], params[1], session.get(TagRule)) case Operation.ImportTagRules: - rules = [TagRule(**row) for row in self.load(params[0])] + rules = [TagRule(**row) for row in self.load(params[0], params[1])] if self.certify(rules): with self.db.session() as session: @@ -316,12 +317,12 @@ class Manager: case Operation.ExportCategories: with self.db.session() as session: - self.dump(params[0], session.get(Category)) + self.dump(params[0], params[1], session.get(Category)) case Operation.ImportCategories: # rules = [Category(**row) for row in self.load(params[0])] categories = [] - for row in self.load(params[0]): + for row in self.load(params[0], params[1]): category = Category(row["name"], row["group"]) if len(row["rules"]) > 0: # Only category rules could have been created with a rule @@ -340,10 +341,12 @@ class Manager: case Operation.ExportCategoryGroups: with self.db.session() as session: - self.dump(params[0], session.get(CategoryGroup)) + self.dump(params[0], params[1], session.get(CategoryGroup)) case Operation.ImportCategoryGroups: - groups = [CategoryGroup(**row) for row in self.load(params[0])] + groups = [ + CategoryGroup(**row) for row in self.load(params[0], params[1]) + ] if self.certify(groups): with self.db.session() as session: @@ -364,14 +367,26 @@ class Manager: return TransactionCategory(category, selector) @staticmethod - def dump(fn, sequence): - with open(fn, "wb") as f: - pickle.dump([e.format for e in sequence], f) + def dump(fn, format, sequence): + if format == "pickle": + with open(fn, "wb") as f: + pickle.dump([e.format for e in sequence], f) + elif format == "csv": + with open(fn, "w", newline="") as f: + csv.writer(f).writerows([e.format.values() for e in sequence]) + else: + print("format not well specified") @staticmethod - def load(fn): - with open(fn, "rb") as f: - return pickle.load(f) + def load(fn, format): + if format == "pickle": + with open(fn, "rb") as f: + return pickle.load(f) + elif format == "csv": + raise Exception("CSV import not supported") + else: + print("format not well specified") + return [] @staticmethod def certify(imports: list) -> bool: