[Refactor] CLI argparser passes options to Manager
Move all BL to the manager. The ArgParser now only parses the CLI arguments and creates a command which contains which command was run. In turn, this information is passed to the manager, which will run the appropriate business logic. This will make it easier to add new options, separating the parsing of the CLI options from the implementation of the logic. It also simplifies any future effort in adding a different input (e.g. GUI). Warning: some function were commented out, this is only a tracer bullet.
This commit is contained in:
parent
be67612f67
commit
882a77d24c
5
main.py
5
main.py
@ -1,4 +1,5 @@
|
||||
from pfbudget import run
|
||||
from pfbudget import Manager, run
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
command, args = run()
|
||||
Manager(command).start(args)
|
||||
|
||||
@ -3,5 +3,6 @@ __author__ = "Luís Murta"
|
||||
__version__ = "0.1"
|
||||
|
||||
from pfbudget.core.categories import categorize_data
|
||||
from pfbudget.core.manager import Manager
|
||||
from pfbudget.cli.runnable import run
|
||||
from pfbudget.input.parsers import parse_data
|
||||
|
||||
@ -2,8 +2,8 @@ from pathlib import Path
|
||||
import argparse
|
||||
import re
|
||||
|
||||
from pfbudget.common.types import Command
|
||||
from pfbudget.core.categories import categorize_data
|
||||
from pfbudget.core.manager import Manager
|
||||
from pfbudget.input.json import JsonParser
|
||||
from pfbudget.input.nordigen import NordigenInput
|
||||
from pfbudget.db.sqlite import DatabaseClient
|
||||
@ -27,7 +27,7 @@ class DataFileMissing(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
def argparser() -> argparse.ArgumentParser:
|
||||
|
||||
help = argparse.ArgumentParser(add_help=False)
|
||||
help.add_argument(
|
||||
@ -74,7 +74,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_init.set_defaults(func=lambda args: manager.init())
|
||||
p_init.set_defaults(command=Command.Init)
|
||||
|
||||
"""
|
||||
Exporting
|
||||
@ -100,7 +100,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
p_parse.add_argument("--bank", nargs=1, type=str)
|
||||
p_parse.add_argument("--creditcard", nargs=1, type=str)
|
||||
p_parse.add_argument("--category", nargs=1, type=int)
|
||||
p_parse.set_defaults(func=lambda args: parse(manager, args))
|
||||
p_parse.set_defaults(command=Command.Parse)
|
||||
|
||||
"""
|
||||
Categorizing
|
||||
@ -111,9 +111,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_categorize.set_defaults(
|
||||
func=lambda args: manager.categorize(vars(args))
|
||||
)
|
||||
p_categorize.set_defaults(command=Command.Categorize)
|
||||
|
||||
"""
|
||||
Graph
|
||||
@ -168,7 +166,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
"--requisition", type=str, nargs=1, help="requisition option help"
|
||||
)
|
||||
p_register.add_argument("--invert", action="store_true")
|
||||
p_register.set_defaults(func=lambda args: manager.register(vars(args)))
|
||||
p_register.set_defaults(command=Command.Register)
|
||||
|
||||
"""
|
||||
Unregister bank
|
||||
@ -180,7 +178,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_register.add_argument("bank", type=str, nargs=1, help="bank option help")
|
||||
p_register.set_defaults(func=lambda args: manager.unregister(vars(args)))
|
||||
p_register.set_defaults(command=Command.Unregister)
|
||||
|
||||
"""
|
||||
Nordigen API
|
||||
@ -191,7 +189,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_nordigen_access.set_defaults(func=lambda args: NordigenInput(manager).token())
|
||||
p_nordigen_access.set_defaults(command=Command.Token)
|
||||
|
||||
"""
|
||||
(Re)new bank requisition ID
|
||||
@ -204,11 +202,7 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
)
|
||||
p_nordigen_access.add_argument("name", nargs=1, type=str)
|
||||
p_nordigen_access.add_argument("country", nargs=1, type=str)
|
||||
p_nordigen_access.set_defaults(
|
||||
func=lambda args: NordigenInput(manager).requisition(
|
||||
args.name[0], args.country[0]
|
||||
)
|
||||
)
|
||||
p_nordigen_access.set_defaults(command=Command.Renew)
|
||||
|
||||
"""
|
||||
Downloading through Nordigen API
|
||||
@ -222,40 +216,40 @@ def argparser(manager: Manager) -> argparse.ArgumentParser:
|
||||
p_nordigen_download.add_argument("--id", nargs="+", type=str)
|
||||
p_nordigen_download.add_argument("--name", nargs="+", type=str)
|
||||
p_nordigen_download.add_argument("--all", action="store_true")
|
||||
p_nordigen_download.set_defaults(func=lambda args: download(manager, args))
|
||||
p_nordigen_download.set_defaults(command=Command.Download)
|
||||
|
||||
"""
|
||||
List available banks on Nordigen API
|
||||
"""
|
||||
p_nordigen_list = subparsers.add_parser(
|
||||
"list",
|
||||
description="Lists banks in {country}",
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_nordigen_list.add_argument("country", nargs=1, type=str)
|
||||
p_nordigen_list.set_defaults(func=lambda args: nordigen_banks(manager, args))
|
||||
# """
|
||||
# List available banks on Nordigen API
|
||||
# """
|
||||
# p_nordigen_list = subparsers.add_parser(
|
||||
# "list",
|
||||
# description="Lists banks in {country}",
|
||||
# parents=[help],
|
||||
# formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
# )
|
||||
# p_nordigen_list.add_argument("country", nargs=1, type=str)
|
||||
# p_nordigen_list.set_defaults(func=lambda args: nordigen_banks(manager, args))
|
||||
|
||||
"""
|
||||
Nordigen JSONs
|
||||
"""
|
||||
p_nordigen_json = subparsers.add_parser(
|
||||
"json",
|
||||
description="",
|
||||
parents=[help],
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
p_nordigen_json.add_argument("json", nargs=1, type=str)
|
||||
p_nordigen_json.add_argument("bank", nargs=1, type=str)
|
||||
p_nordigen_json.add_argument("--invert", action=argparse.BooleanOptionalAction)
|
||||
p_nordigen_json.set_defaults(
|
||||
func=lambda args: manager.parser(JsonParser(vars(args)))
|
||||
)
|
||||
# """
|
||||
# Nordigen JSONs
|
||||
# """
|
||||
# p_nordigen_json = subparsers.add_parser(
|
||||
# "json",
|
||||
# description="",
|
||||
# parents=[help],
|
||||
# formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
# )
|
||||
# p_nordigen_json.add_argument("json", nargs=1, type=str)
|
||||
# p_nordigen_json.add_argument("bank", nargs=1, type=str)
|
||||
# p_nordigen_json.add_argument("--invert", action=argparse.BooleanOptionalAction)
|
||||
# p_nordigen_json.set_defaults(
|
||||
# func=lambda args: manager.parser(JsonParser(vars(args)))
|
||||
# )
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def parse(manager: Manager, args):
|
||||
def parse(manager, args):
|
||||
"""Parses the contents of the path in args to the selected database.
|
||||
|
||||
Args:
|
||||
@ -305,17 +299,17 @@ def report(args):
|
||||
pfbudget.reporting.report.detailed(DatabaseClient(args.database), start, end)
|
||||
|
||||
|
||||
def nordigen_banks(manager: Manager, args):
|
||||
input = NordigenInput(manager)
|
||||
input.list(vars(args)["country"][0])
|
||||
# def nordigen_banks(manager: Manager, args):
|
||||
# input = NordigenInput(manager)
|
||||
# input.list(vars(args)["country"][0])
|
||||
|
||||
|
||||
def download(manager: Manager, args):
|
||||
def download(manager, args: dict):
|
||||
start, end = pfbudget.utils.parse_args_period(args)
|
||||
manager.parser(NordigenInput(manager, vars(args), start, end))
|
||||
manager.parser(NordigenInput(manager, args, start, end))
|
||||
|
||||
|
||||
def run():
|
||||
manager = Manager(DEFAULT_DB)
|
||||
args = argparser(manager).parse_args()
|
||||
args.func(args)
|
||||
args = vars(argparser().parse_args())
|
||||
assert "command" in args, "No command selected"
|
||||
return args["command"], args
|
||||
|
||||
@ -4,6 +4,17 @@ from decimal import Decimal, InvalidOperation
|
||||
from enum import Enum, auto
|
||||
|
||||
|
||||
class Command(Enum):
|
||||
Init = auto()
|
||||
Parse = auto()
|
||||
Download = auto()
|
||||
Categorize = auto()
|
||||
Register = auto()
|
||||
Unregister = auto()
|
||||
Token = auto()
|
||||
Renew = auto()
|
||||
|
||||
|
||||
class TransactionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ from datetime import timedelta
|
||||
class Categorizer:
|
||||
options = {}
|
||||
|
||||
def __init__(self, args: dict):
|
||||
def __init__(self):
|
||||
self.options["null_days"] = 4
|
||||
|
||||
def categorize(self, transactions: list[Transaction]):
|
||||
@ -21,6 +21,7 @@ class Categorizer:
|
||||
self._nullify(transactions)
|
||||
|
||||
def _nullify(self, transactions: list[Transaction]):
|
||||
count = 0
|
||||
matching = []
|
||||
for transaction in transactions:
|
||||
for cancel in (
|
||||
@ -40,4 +41,7 @@ class Categorizer:
|
||||
transaction.category = TransactionCategory(name="null")
|
||||
cancel.category = TransactionCategory(name="null")
|
||||
matching.extend([transaction, cancel])
|
||||
count += 2
|
||||
break
|
||||
|
||||
print(f"Nullified {count} transactions")
|
||||
|
||||
@ -1,13 +1,62 @@
|
||||
from pfbudget.input.input import Input
|
||||
from pfbudget.input.nordigen import NordigenClient
|
||||
from pfbudget.input.parsers import parse_data
|
||||
from pfbudget.db.client import DbClient
|
||||
from pfbudget.common.types import Command
|
||||
from pfbudget.core.categorizer import Categorizer
|
||||
from pfbudget.utils import convert
|
||||
|
||||
from pfbudget.cli.runnable import download, parse
|
||||
|
||||
|
||||
class Manager:
|
||||
def __init__(self, url: str):
|
||||
self._db = DbClient(url)
|
||||
def __init__(self, command: Command):
|
||||
self.__command = command
|
||||
match (command):
|
||||
case Command.Init:
|
||||
pass
|
||||
case Command.Parse:
|
||||
pass
|
||||
case Command.Download:
|
||||
pass
|
||||
case Command.Categorize:
|
||||
pass
|
||||
case Command.Register:
|
||||
pass
|
||||
case Command.Unregister:
|
||||
pass
|
||||
case Command.Token:
|
||||
pass
|
||||
case Command.Renew:
|
||||
pass
|
||||
|
||||
def start(self, args):
|
||||
match (self.__command):
|
||||
case Command.Init:
|
||||
pass
|
||||
case Command.Parse:
|
||||
# TODO this is a monstrosity, remove when possible
|
||||
self._db = DbClient(args["database"])
|
||||
parse(self, args)
|
||||
case Command.Download:
|
||||
# TODO this is a monstrosity, remove when possible
|
||||
self._db = DbClient(args["database"])
|
||||
download(self, args)
|
||||
case Command.Categorize:
|
||||
self._db = DbClient(args["database"])
|
||||
self.categorize(args)
|
||||
case Command.Register:
|
||||
# self._db = DbClient(args["database"])
|
||||
# self.register(args)
|
||||
pass
|
||||
case Command.Unregister:
|
||||
# self._db = DbClient(args["database"])
|
||||
# self.unregister(args)
|
||||
pass
|
||||
case Command.Token:
|
||||
NordigenClient(self).token()
|
||||
case Command.Renew:
|
||||
NordigenClient(self).requisition(args["name"], args["country"])
|
||||
|
||||
# def init(self):
|
||||
# client = DatabaseClient(self.__db)
|
||||
|
||||
@ -59,21 +59,22 @@ def find_credit_institution(fn, banks, creditcards):
|
||||
return bank, cc
|
||||
|
||||
|
||||
def parse_args_period(args):
|
||||
def parse_args_period(args: dict):
|
||||
start, end = date.min, date.max
|
||||
if args.start:
|
||||
start = datetime.strptime(args.start[0], "%Y/%m/%d").date()
|
||||
print(args)
|
||||
if args["start"]:
|
||||
start = datetime.strptime(args["start"][0], "%Y/%m/%d").date()
|
||||
|
||||
if args.end:
|
||||
end = datetime.strptime(args.end[0], "%Y/%m/%d").date()
|
||||
if args["end"]:
|
||||
end = datetime.strptime(args["end"][0], "%Y/%m/%d").date()
|
||||
|
||||
if args.interval:
|
||||
start = datetime.strptime(args.interval[0], "%Y/%m/%d").date()
|
||||
end = datetime.strptime(args.interval[1], "%Y/%m/%d").date()
|
||||
if args["interval"]:
|
||||
start = datetime.strptime(args["interval"][0], "%Y/%m/%d").date()
|
||||
end = datetime.strptime(args["interval"][1], "%Y/%m/%d").date()
|
||||
|
||||
if args.year:
|
||||
start = datetime.strptime(args.year[0], "%Y").date()
|
||||
end = datetime.strptime(str(int(args.year[0]) + 1), "%Y").date() - timedelta(
|
||||
if args["year"]:
|
||||
start = datetime.strptime(args["year"][0], "%Y").date()
|
||||
end = datetime.strptime(str(int(args["year"][0]) + 1), "%Y").date() - timedelta(
|
||||
days=1
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user