def test_add_item(): repo = Repository() repo.add_item(1) assert repo.get_items() == [1] repo.undo() assert repo.get_items() == []
def test_replace_item(): repo = Repository() repo.add_item(0) repo.add_item(1) repo.add_item(1) repo.add_item(1) repo.replace_item(lambda item: item == 1, 0) assert repo.get_items() == [0, 0, 1, 1] repo.undo() assert repo.get_items() == [0, 1, 1, 1]
def test_get_items(): repo = Repository() repo.add_item(0) repo.add_item(1) assert repo.get_item(lambda item: item == 1) == 1 repo.add_item(1) assert repo.get_items() == [0, 1, 1] assert repo.get_items(lambda item: item == 1) == [1, 1] assert not repo.get_items(lambda item: item > 1) repo.add_item(2) assert repo.get_items(lambda item: item > 1) == [2]
class TransactionCommands(clisys.CLISys): def __init__(self): super().__init__() self.__repo = Repository() self.init_repo() @clisys.command(name='help') def help(self, args): """ Displays help for all commands or a single command. help help <command> """ count = len(args) commands = self.get_commands() if count == 0: for cmd_name, cmd in commands.items(): print(f'{cmd_name}: {cmd.__doc__}') elif count == 1: cmd_name = args[0] if not (cmd_name in commands.keys()): raise clisys.InvalidArgument(args[0]) cmd = commands[cmd_name] print(f'{cmd_name}: {cmd.__doc__}') @clisys.command(name='test') def test(self, args): """ Test command. """ print('TEST') @clisys.command(name='exit') def exit_command(self, args): """ Exits the program. """ exit(0) @clisys.command(name='add') def add_transaction(self, args): """ Add a transaction to the list. add <value> <type> <description> """ try: value = int(args[0]) except ValueError: raise clisys.InvalidArgument(args[0]) type = args[1] description = args[2] transaction = Transaction(int(datetime.today().strftime('%d')), value, type, description) self.__repo.add_item(transaction) @clisys.command(name='insert') def insert_transaction(self, args): """ Insert a transaction in the list. insert <day> <value> <type> <description> """ try: day = int(args[0]) except ValueError: raise clisys.InvalidArgument(args[0]) try: value = int(args[1]) except ValueError: raise clisys.InvalidArgument(args[1]) type = args[2] description = args[3] transaction = Transaction(day, value, type, description) self.__repo.add_item(transaction) @clisys.command(name='remove') def remove_transaction(self, args): """ Remove transactions from the list. remove <day> remove <start day> to <end day> remove <type> """ count = len(args) if count == 1: try: day = int(args[0]) self.__repo.remove_items(lambda t: t.get_day() == day) except ValueError: type = args[0] self.__repo.remove_items(lambda t: t.get_type() == type) elif count == 3: if args[1] != 'to': raise clisys.InvalidArgument(args[1]) start_day = int(args[0]) end_day = int(args[2]) self.__repo.remove_items( lambda t: start_day <= t.get_day() <= end_day) else: raise clisys.InvalidArgumentCount @clisys.command(name='replace') def replace_transaction(self, args): """ Replace the amount of a transaction with a given value. replace <day> <type> <description> with <value> """ if len(args) != 5: raise clisys.InvalidArgumentCount if args[3] != 'with': raise clisys.InvalidArgument(args[3]) try: day = int(args[0]) except ValueError: raise clisys.InvalidArgument(args[0]) type = args[1] description = args[2] try: value = int(args[4]) except ValueError: raise clisys.InvalidArgument(args[4]) self.__repo.replace_item( lambda t: t.get_day() == day and t.get_type() == type and t. get_description() == description, Transaction(day, value, type, description)) @clisys.command(name='list') def list_transactions(self, args): """ Display the list of transactions. list list <type> list [ < | = | > ] <value> list balance <day> """ count = len(args) if count == 0: display_transactions(self.__repo.get_items()) elif count == 1: type = args[0] display_transactions( self.__repo.get_items(lambda t: t.get_type() == type)) elif count == 2: option = args[0] if option == 'balance': try: day = int(args[1]) except ValueError: raise clisys.InvalidArgument(args[1]) balance = get_balance(self.__repo, day) print(f"Balance on day {day}: {balance}") elif option in ['<', '=', '>']: try: amount = int(args[1]) except ValueError: raise clisys.InvalidArgument(args[1]) if option == '<': display_transactions( self.__repo.get_items( lambda t: t.get_money_amount() < amount)) elif option == '=': display_transactions( self.__repo.get_items( lambda t: t.get_money_amount() == amount)) elif option == '>': display_transactions( self.__repo.get_items( lambda t: t.get_money_amount() > amount)) else: raise clisys.InvalidArgument(args[0]) else: raise clisys.InvalidArgumentCount @clisys.command(name='sum') def sum_transactions(self, args): """ Displays the total amount from a transaction type. sum <type> """ if len(args) > 1: raise clisys.InvalidArgumentCount type = args[0] result = get_sum(self.__repo, type) print(f'Total amount from "{type}" transactions: {result}') @clisys.command(name='max') def max_transaction(self, args): if len(args) != 2: raise clisys.InvalidArgumentCount type = args[0] try: day = int(args[1]) except ValueError: raise clisys.InvalidArgument(args[1]) result = get_max(self.__repo, type, day) if result is None: print(f'No transaction of type "{type}" on day {day}.') else: print( f'The maximum "{type}" transaction on day {day}: "{result.get_description()}: {result.get_money_amount()}"' ) @clisys.command(name='filter') def filter_transactions(self, args): """ Filters the transactions. filter <type> filter <type> <value> """ count = len(args) if count == 1: type = args[0] self.__repo.remove_items(lambda t: t.get_type() != type) elif count == 2: type = args[0] try: value = int(args[1]) except ValueError: raise clisys.InvalidArgument([args[1]]) self.__repo.remove_items(lambda t: t.get_type() != type or t. get_money_amount() >= value) print('Transactions filtered successfully!') @clisys.command(name='undo') def undo(self, args): """ Undo the last command that changed the transactions list. undo """ try: self.__repo.undo() print('Undo executed successfully!') except cmdsys.EmptyActionsStack: print('Nothing to undo.') @clisys.command(name='redo') def redo(self, args): """ Redo the last undo-ed command. redo """ try: self.__repo.redo() print('Redo executed successfully!') except cmdsys.EmptyUndoStack: print('Nothing to redo.') @clisys.exception_handler def handle_exceptions(self, exception: Exception): """ Handles exceptions raised in commands. :param exception: The exception. :return: """ try: raise exception except clisys.InvalidCommand as e: print(f'Invalid command: "{str(e.command_name)}" .') except clisys.InvalidArgument as e: print(f'Invalid argument: "{str(e.argument_name)}" .') except clisys.InvalidArgumentCount: print(f'Invalid argument count.') @clisys.input_handler def get_input(self): """ Gets the input and returns it as a list :return: A list of strings. """ i = input('\n> ') i = re.split(r' +', i) return i def init_repo(self): self.__repo.add_item(Transaction(2, 1909, 'in', 'freelancing')) self.__repo.add_item(Transaction(24, 178, 'out', 'food')) self.__repo.add_item(Transaction(1, 1200, 'out', 'rent')) self.__repo.add_item(Transaction(14, 54, 'out', 'food')) self.__repo.add_item(Transaction(14, 55023, 'in', 'salary')) self.__repo.add_item(Transaction(16, 550, 'in', 'freelancing')) self.__repo.add_item(Transaction(23, 1200, 'out', 'project')) self.__repo.add_item(Transaction(2, 230, 'out', 'food')) self.__repo.add_item(Transaction(16, 176, 'out', 'food')) self.__repo.add_item(Transaction(5, 188, 'out', 'food'))
def test_get_balance(): repo = Repository() repo.add_item(Transaction(2, 1909, 'in', 'freelancing')) repo.add_item(Transaction(24, 178, 'out', 'food')) repo.add_item(Transaction(1, 1200, 'out', 'rent')) repo.add_item(Transaction(14, 54, 'out', 'food')) repo.add_item(Transaction(14, 55023, 'in', 'salary')) repo.add_item(Transaction(16, 550, 'in', 'freelancing')) repo.add_item(Transaction(23, 1200, 'out', 'project')) repo.add_item(Transaction(2, 230, 'out', 'food')) repo.add_item(Transaction(16, 176, 'out', 'food')) repo.add_item(Transaction(5, 188, 'out', 'food')) assert get_balance(repo, 2) == 479 assert get_balance(repo, 5) == 291
def test_get_max(): repo = Repository() repo.add_item(Transaction(2, 1909, 'in', 'freelancing')) repo.add_item(Transaction(2, 178, 'out', 'food')) repo.add_item(Transaction(1, 1200, 'out', 'rent')) repo.add_item(Transaction(14, 54, 'out', 'food')) repo.add_item(Transaction(14, 55023, 'in', 'salary')) repo.add_item(Transaction(14, 550, 'in', 'freelancing')) repo.add_item(Transaction(23, 1200, 'out', 'project')) repo.add_item(Transaction(2, 230, 'out', 'food')) repo.add_item(Transaction(16, 176, 'out', 'food')) repo.add_item(Transaction(5, 188, 'out', 'food')) assert get_max(repo, 'in', 14).get_money_amount() == 55023 assert get_max(repo, 'out', 2).get_money_amount() == 230
class UI(clisys.CLISys): def __init__(self): super().__init__() self.__repo = Repository() self.init_repo() @clisys.command('1', description='Add expense.') def add_expense(self, args): try: expense = read_expense() except ValueError: raise ExpenseError('Invalid expense.') self.__repo.add_item(expense) print('Expense added successfully!') @clisys.command('2', description='Show expenses.') def list_expenses(self, args): """ Displays the list of expenses. :param args: :return: """ expenses = self.__repo.get_items() print('Id\t|\tDay\t|\tAmount\t|\tType', end='\n\n') for i, expense in enumerate(expenses): print(f'{i + 1}.\t\t{expense.day}\t\t{expense.money_amount}\t\t\t{expense.type}') @clisys.command(name='3', description='Filter expenses.') def filter_expenses(self, args): """ Filter the expenses list :param args: :return: """ try: min_value = int(input('Input the minimum value: ')) except ValueError: raise ValueError('Invalid minimum value.') self.__repo.remove_items(lambda e: e.money_amount <= min_value) print('Expenses filtered successfully!') @clisys.command(name='4', description='Undo.') def undo(self, args): """ Undo the last command that changed the expenses list. :param args: :return: """ self.__repo.undo() print('Undo executed successfully!') @clisys.command(name='5', description='Redo.') def redo(self, args): """ Undo the last command that changed the expenses list. :param args: :return: """ self.__repo.redo() print('Redo executed successfully!') @clisys.command(name='-1', description='Exit.') def exit_program(self, args): """ Exits the program. """ exit(0) @clisys.exception_handler def handle_exceptions(self, exception: Exception): """ Handles exceptions raised in commands. :param exception: The exception. :return: """ try: raise exception except clisys.InvalidCommand as e: print(f'Invalid option: "{str(e.command_name)}" .') except clisys.InvalidArgument as e: print(f'Invalid argument: "{str(e.argument_name)}" .') except clisys.InvalidArgumentCount: print('Invalid argument count.') except cmdsys.EmptyActionsStack: print('Nothing to undo.') except cmdsys.EmptyUndoStack: print('Nothing to redo.') except ExpenseError as e: print(e) except ValueError as e: print(e) def display_options(self): """ Displays the list of options. :return: """ print() options = list(self.get_commands().values()) options.sort(key=lambda op: op.name) for option in options: print(f'{option.name}. {option.description}') @clisys.input_handler def get_option(self): """ Gets the input and returns it as a list :return: A list of strings. (first element is the name of the command) """ self.display_options() i = input('\nOption: ') return [i] def init_repo(self): self.__repo.add_item(Expense(1, 10, 'food')) self.__repo.add_item(Expense(1, 120, 'internet')) self.__repo.add_item(Expense(1, 112, 'food')) self.__repo.add_item(Expense(4, 20, 'food')) self.__repo.add_item(Expense(4, 100, 'electricity')) self.__repo.add_item(Expense(6, 980, 'phone')) self.__repo.add_item(Expense(8, 1, 'food')) self.__repo.add_item(Expense(8, 16, 'food')) self.__repo.add_item(Expense(23, 100, 'food')) self.__repo.add_item(Expense(30, 233, 'gas'))