# Bank Account Example with Function-Level Decorator
# Python 3 Reflexive Metaprogramming
# H. Conrad Cunningham

# Developed for CSci 658, Software Language Engineering, Spring 2018

#234567890123456789012345678901234567890123456789012345678901234567890

# 2018-03-29: (V1) debug decorator adapted from Beazley's 2013
#             Metaprogramming tutorial
# 2018-04-02: (V1a) Changed balance to get_balance

from functools import wraps, partial

def debug(func = None, *, prefix = ''): 
    if func is None:
        return partial(debug, prefix=prefix)
    msg = prefix + func.__qualname__
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(msg)
        return func(*args, **kwargs)
    return wrapper

class Account:
    def __init__(self):
        self._bal = 0

    @debug
    def deposit(self,amt):
        self._bal += amt

    @debug
    def withdraw(self,amt):
        if amt <= self._bal:
            self._bal -= amt
        else:
            print(f'Insufficient funds for withdrawal of {amt}')

    @debug
    def get_balance(self):
        return self._bal

    def __str__(self):
        return f'Account with balance {self._bal}'

if __name__ == '__main__':
    acct = Account()
    print(f'Account: {acct}')
    acct.deposit(100)
    print(f'Deposit 100: {acct.get_balance()}')
    acct.withdraw(60)
    print(f'Withdraw 60: {acct.get_balance()}')

