From f721e6a910bd40301dc06d7c43a8b1e57942bd1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Murta?= Date: Fri, 9 Dec 2022 19:43:09 +0000 Subject: [PATCH] [Refactor] Decouple CLI arguments from Manager The Manager doesn't need to know that it was called from the CLI, so it now is initialized with the database and performs an action, based on the operation it receives and its parameters. The work isn't finished, some Manager actions are still based on the CLI arguments. The CLI logic and creation of parameters to pass to the manager have been moved to the __main__.py file, which brings it to line to the program being called as a package from the command line. --- pfbudget/__init__.py | 3 ++ pfbudget/__main__.py | 72 ++++++++++++++++++++++++++++++++++++++-- pfbudget/core/manager.py | 30 ++++++----------- pfbudget/db/client.py | 22 +++--------- 4 files changed, 88 insertions(+), 39 deletions(-) diff --git a/pfbudget/__init__.py b/pfbudget/__init__.py index 2a836a1..abbb667 100644 --- a/pfbudget/__init__.py +++ b/pfbudget/__init__.py @@ -2,7 +2,10 @@ __all__ = ["argparser", "Manager", "parse_data", "categorize_data"] __author__ = "Luís Murta" __version__ = "0.1" +from pfbudget.common.types import Operation from pfbudget.core.categories import categorize_data from pfbudget.core.manager import Manager from pfbudget.cli.runnable import argparser from pfbudget.input.parsers import parse_data + +import pfbudget.db.model as types diff --git a/pfbudget/__main__.py b/pfbudget/__main__.py index a5fa7de..023331e 100644 --- a/pfbudget/__main__.py +++ b/pfbudget/__main__.py @@ -4,5 +4,73 @@ import pfbudget if __name__ == "__main__": argparser = pfbudget.argparser() args = vars(argparser.parse_args()) - assert "op" in args, "No operation selected" - pfbudget.Manager(args["op"], args).start() + + assert "op" in args, "No pfbudget.Operation selected" + op: pfbudget.Operation = args["op"] + + assert "database" in args, "No database selected" + db = args["database"] + + params = None + match (op): + case pfbudget.Operation.CategoryAdd: + assert args.keys() >= {"category", "group"}, "argparser ill defined" + params = [ + pfbudget.types.Category(cat, args["group"][0]) + for cat in args["category"] + ] + + case pfbudget.Operation.CategoryUpdate: + assert args.keys() >= {"category", "group"}, "argparser ill defined" + params = [pfbudget.types.Category(cat) for cat in args["category"]] + params.append(args["group"][0]) + + case pfbudget.Operation.CategoryRemove: + assert "category" in args, "argparser ill defined" + params = [pfbudget.types.Category(cat) for cat in args["category"]] + + case pfbudget.Operation.CategorySchedule: + assert args.keys() >= { + "category", + "period", + "frequency", + }, "argparser ill defined" + + params = [ + pfbudget.types.CategorySchedule( + cat, True, args["period"][0], args["frequency"][0] + ) + for cat in args["category"] + ] + + case pfbudget.Operation.CategoryRule: + assert args.keys() >= { + "category", + "date", + "description", + "bank", + "min", + "max", + }, "argparser ill defined" + + params = [ + pfbudget.types.CategoryRule( + cat, + args["date"][0] if args["date"] else None, + args["description"][0] if args["description"] else None, + args["bank"][0] if args["bank"] else None, + args["min"][0] if args["min"] else None, + args["max"][0] if args["max"] else None, + ) + for cat in args["category"] + ] + + case pfbudget.Operation.GroupAdd: + assert "group" in args, "argparser ill defined" + params = [pfbudget.types.CategoryGroup(group) for group in args["group"]] + + case pfbudget.Operation.GroupRemove: + assert "group" in args, "argparser ill defined" + params = [pfbudget.types.CategoryGroup(group) for group in args["group"]] + + pfbudget.Manager(db, args).action(op, params) diff --git a/pfbudget/core/manager.py b/pfbudget/core/manager.py index fb0d54f..2227ccf 100644 --- a/pfbudget/core/manager.py +++ b/pfbudget/core/manager.py @@ -11,15 +11,14 @@ from pfbudget.cli.runnable import download, parse class Manager: - def __init__(self, op: Operation, args: dict): - self._operation = op + def __init__(self, db: str, args: dict): self._args = args + print(args) - assert "database" in args, "ArgParser didn't include db" - self._db = args["database"] + self._db = db - def start(self): - match (self._operation): + def action(self, op: Operation, params: list): + match (op): case Operation.Init: pass case Operation.Parse: @@ -49,28 +48,19 @@ class Manager: case Operation.CategoryAdd: with self.db.session() as session: - for category in self.args["category"]: - session.addcategory( - Category(name=category, group=self.args["group"]) - ) + session.addcategories(params) case Operation.CategoryUpdate: with self.db.session() as session: - session.updategroup( - [Category(name=category) for category in self.args["category"]], - self.args["group"][0], - ) + session.updategroup(*params) case Operation.CategoryRemove: with self.db.session() as session: - session.removecategory( - [Category(name=category) for category in self.args["category"]] - ) + session.removecategories(params) case Operation.CategorySchedule: - assert ( - "period" in self.args and "frequency" in self.args - ), "Schedule not well defined" + with self.db.session() as session: + session.updateschedules(params) case Operation.CategoryRule: with self.db.session() as session: diff --git a/pfbudget/db/client.py b/pfbudget/db/client.py index 9e44a93..28c2b39 100644 --- a/pfbudget/db/client.py +++ b/pfbudget/db/client.py @@ -84,10 +84,10 @@ class DbClient: def add(self, transactions: list[Transaction]): self.__session.add_all(transactions) - def addcategory(self, category: Category): - self.__session.add(category) + def addcategories(self, category: list[Category]): + self.__session.add_all(category) - def removecategory(self, categories: list[Category]): + def removecategories(self, categories: list[Category]): stmt = delete(Category).where( Category.name.in_([cat.name for cat in categories]) ) @@ -101,20 +101,8 @@ class DbClient: ) self.__session.execute(stmt) - def updateschedules( - self, categories: list[Category], schedule: CategorySchedule - ): - stmt = insert(CategorySchedule).values( - [ - dict( - name=cat.name, - recurring=schedule.recurring, - period=schedule.period, - period_multiplier=schedule.period_multiplier, - ) - for cat in categories - ] - ) + def updateschedules(self, schedules: list[CategorySchedule]): + stmt = insert(CategorySchedule).values([asdict(s) for s in schedules]) stmt = stmt.on_conflict_do_update( index_elements=[CategorySchedule.name], set_=dict(