Build a Budget App - Build a Budget App

Tell us what’s happening:

I’ve spent alot of time on this. When i run my code in VS code i get the same exact spacing as the example provided, ive checked line by line. I also tested and my final_chart is a string which the test asks for.

The F12 test is confusing but I’m basically failing step 17 and up which doesn’t make sense. F12 tells me this:
{message: ‘Unspecified AssertionError’, showDiff: false, actual: null, expected: undefined, stack: ‘AssertionError: Unspecified AssertionError\n at …t-runner/9.0.0/python-test-evaluator.js:2:156979)’

In VS code my output looks like this:

class Category():
    def __init__(self,name):
        self.name = name
        self.ledger = []
        self.running_total = 0
        self.total_spend = 0

    def __str__(self):
        print(self.ledger)
        pass    
    #### ALLL CODE NEEDS TO BE UPDATED TO APPEND DICTIONARYS NOT FSTRINGs
    def deposit(self,amount,description=''):
        deposit_amount = {'amount':amount, 'description': description}
        self.ledger.append(deposit_amount)
        self.running_total = self.running_total + amount
        

    def withdraw(self,amount,description=''):
        if self.check_funds(amount):
            amount = -amount
            withdrawl_amount = {'amount': amount, 'description': description}
            self.ledger.append(withdrawl_amount)
            self.running_total = self.running_total + amount
            self.total_spend = self.total_spend + amount
            return True if self.running_total >=0 else False
        else:
            return False
        
    def get_balance(self):
        return self.running_total
    
    
    def transfer(self,amount,category):
        if self.check_funds(amount):
            self.withdraw(amount,f'Transfer to {category.name}')
            category.deposit(amount,f'Transfer from {self.name}')
            
            return True if self.running_total >=0 else False
        else:
            return False
    def check_funds(self,amount):
        if amount > self.running_total:
            return False
        else:  
            return True

    #how can i pull out the objects
    def __str__(self):
        receipt_star =  int((30 - len(self.name)) / 2)
        star_ = '*'
        title_ = (f'{receipt_star * star_}{self.name}{receipt_star * star_}\n'
        )
        output = title_
        
        for item in self.ledger:
            description = item['description']
            amount = item['amount']
            amount = float(amount)
            output+= f'{description.ljust(23)[:23]}{amount:>7.2f}\n'
        output+= f'Total: {float(self.running_total):.2f}'
        return output
        

def create_spend_chart(*categories):
    title = 'Percentage spent by category\n'
    final_chart=''
    final_chart +=title
    cat_dict = {}
    sum_total = 0
    marker_ = 'o'
    precentages_ = range(100,0,-10)
    #all spend stored in dict by cat
    for category in categories:
        Category(category)
        cat_dict[category.name] = abs(category.total_spend)
    #calculate sum total for each cat
    for key, value in cat_dict.items():
        value = abs(int(value))
        sum_total = sum_total + value
    #replace the value with new value represented as a whole number
    for key, value in cat_dict.items():
        cat_dict[key] = (value/sum_total)*100

    #convert the dict value to % of total?
    #for key,value in cat_dict:
    for x in range(100,-10,-10):
        row_marker = ''
        final_chart+= (f'{x:>3}|')
        #adding the dots
        for key,value in cat_dict.items():
            value = abs(value)
            row_marker += f" {marker_ if value >= x else ' '} "
        final_chart+=row_marker + '\n'
    
    ## print the footer
    footer_ = '    '
    for key in cat_dict:
        footer_ += f"---"
    final_chart+=footer_+'-\n'
    
    #print category letters
    footer_list = []
    length_ = 3
    for key,value in cat_dict.items():
        footer_list.append(key)
    footer_length = max(len(word) for word in footer_list)
    spaces_ = "  "
    footer_cat = ''
    z = len(footer_list)+1
    for num in range(0,footer_length+1):
        z = z-1
        footer_cat = '   '
        for cat in footer_list:
            if num < len(cat):
                y = list(cat)
                y = y[num]
                footer_cat+= f'{y:>3}'
            else:
                footer_cat+='   '
        final_chart += f'{footer_cat}\n'
    
    
    return final_chart

food = Category('Food')
food.deposit(1000, 'initial deposit')
food.withdraw(10.15, 'groceries')
food.withdraw(10.15, 'restaurant and more food for dessert')
food.withdraw(10000,'fraud')
clothing = Category('Clothing')
clothing.deposit(1000,'Money')
clothing.withdraw(500,'FUN')
food.transfer(50, clothing)

video_games = Category('Video Games')
video_games.deposit(1000,"paycheck")
video_games.withdraw(500,'ZELDA')
video_games.withdraw(450,'WOW')
test_ = create_spend_chart(food,clothing,video_games)

#testing my three instances

print(test_)

Your code so far

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36

Challenge Information:

Build a Budget App - Build a Budget App

1 Like

Relevant part from the console is this one:

Traceback (most recent call last):
   File "/home/pyodide/test_module.py", line 27, in test_create_spend_chart_names_three_categories
     chart = budget.create_spend_chart([self.business, self.food, self.entertainment])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/pyodide/budget.py", line 75, in create_spend_chart
     cat_dict[category.name] = abs(category.total_spend)
                                   ^^^^^^^^^^^^^^^^^^^^
 AttributeError: 'list' object has no attribute 'total_spend'

This is caused because create_spend_chart is used slightly differently in tests. It’s expected to receive list with categories as an argument, instead of accepting multiple arguments.

1 Like

Is someone from admin team able to help then? Is it an issue with the test or my solution lol

Your create_spend_chart accepts multiple arguments, while it should take single argument - list with categories.

1 Like

you can think of it like this categories = [food, clothing, drinks, snacks]

food = Category(‘Food’)
clothing = Category(‘Clothing’)
drinks = Category(‘Drinks’)
snacks = Category(‘Snacks’)

and then you have to build the code around the fact that the categories parameter is 1 singular list that contains multiple Category objects.

Hope that helps you to be able to understand what is actually going on behind the scenes.

Hi Im so close just failing the last two tests:

    1. create_spend_chart chart should have each category name written vertically below the bar. Each line should have the same length, each category should be separated by two spaces, with additional two spaces after the final category.
  • Failed:24. create_spend_chart should print a different chart representation. Check that all spacing is exact. Open your browser console with F12 for more details.

I can prove visually that my spaces are accurate i did a
final_chart = final_chart.replace(’ ,‘.’) which replaces spaces with dots so you can visually see the spacing. I"ve learned so much from this challenge, but trying to game the test when my output looks like it matches is frustrating. can anyone help me with what could be going wrong, advice on how to read the F12 output is appreciated because all is that it has an error that expected undefined but received null?

class Category():
    def __init__(self,name):
        self.name = name
        self.ledger = []
        self.running_total = 0
        self.total_spend = 0

    def __str__(self):
        print(self.ledger)
        pass    
    #### ALLL CODE NEEDS TO BE UPDATED TO APPEND DICTIONARYS NOT FSTRINGs
    def deposit(self,amount,description=''):
        deposit_amount = {'amount':amount, 'description': description}
        self.ledger.append(deposit_amount)
        self.running_total = self.running_total + amount
        

    def withdraw(self,amount,description=''):
        if self.check_funds(amount):
            amount = -amount
            withdrawl_amount = {'amount': amount, 'description': description}
            self.ledger.append(withdrawl_amount)
            self.running_total = self.running_total + amount
            self.total_spend = self.total_spend + amount
            return True if self.running_total >=0 else False
        else:
            return False
        
    def get_balance(self):
        return self.running_total
    
    
    def transfer(self,amount,category):
        if self.check_funds(amount):
            self.withdraw(amount,f'Transfer to {category.name}')
            category.deposit(amount,f'Transfer from {self.name}')
            
            return True if self.running_total >=0 else False
        else:
            return False
    def check_funds(self,amount):
        if amount > self.running_total:
            return False
        else:  
            return True

    #how can i pull out the objects
    def __str__(self):
        receipt_star =  int((30 - len(self.name)) / 2)
        star_ = '*'
        title_ = (f'{receipt_star * star_}{self.name}{receipt_star * star_}\n'
        )
        output = title_
        
        for item in self.ledger:
            description = item['description']
            amount = item['amount']
            amount = float(amount)
            output+= f'{description.ljust(23)[:23]}{amount:>7.2f}\n'
        output+= f'Total: {float(self.running_total):.2f}'
        return output
        

def create_spend_chart(categories):
    title = 'Percentage spent by category\n'
    final_chart=''
    final_chart +=title
    cat_dict = {}
    sum_total = 0
    marker_ = 'o'
    precentages_ = range(100,0,-10)
    #all spend stored in dict by cat
    for category in categories:
        Category(category)
        cat_dict[category.name] = abs(category.total_spend)
    #calculate sum total for each cat
    for key, value in cat_dict.items():
        value = abs(int(value))
        sum_total = sum_total + value
    #replace the value with new value represented as a whole number
    for key, value in cat_dict.items():
        cat_dict[key] = (value/sum_total)*100

    #convert the dict value to % of total?
    #for key,value in cat_dict:
    for x in range(100,-10,-10):
        row_marker = ''
        final_chart+= (f'{x:>3}|')
        #adding the dots
        for key,value in cat_dict.items():
            value = abs(value)
            row_marker += f" {marker_ if value >= x else ' '} "
        final_chart+=row_marker +" " + '\n'
    
    ## print the footer
    footer_ = '    '
    for key in cat_dict:
        footer_ += f"---"
    final_chart+=footer_+'-\n'
    
    #print category letters
    footer_list = []
    length_ = 3
    for key,value in cat_dict.items():
        footer_list.append(key)
    footer_length = max(len(word) for word in footer_list)
    spaces_ = "  "
    footer_cat = ''
    z = len(footer_list)+1
    for num in range(0,footer_length+1):
        z = z-1
        footer_cat = '   '
        for cat in footer_list:
            if num < len(cat):
                y = list(cat)
                y = y[num]
                footer_cat+= f'{y:>3}'
            else:
                footer_cat+='   '
        if num < footer_length:
            final_chart += f'{footer_cat}'+'     '  + '\n'
        else:
            final_chart += f'{footer_cat}'+' '
    
    
    return final_chart

this helped so much, im stuck on one last thing if you hav an opinion

1 Like

Thank you for replying im stuck on one last item

Hi @robkarlson104 ,

Please check the assertion errors in your browser’s console:

'     B  F  E     \n     u  o  n     \n     s  o  t     [201 chars]    ' != 
'     B  F  E  \n     u  o  n  \n     s  o  t  \n     i [147 chars] t  '
'     F  E     \n     o  n     \n     o  t     \n    [162 chars]    ' !=
'     F  E  \n     o  n  \n     o  t  \n     d  e  \n[111 chars] t  '
'Perc[227 chars]  E     \n     u  o  n     \n     s  o  t     [201 chars]    ' !=
'Perc[227 chars]  E  \n     u  o  n  \n     s  o  t  \n     i [147 chars] t  '

You can use this guide on how to interpret the details:


The assertion error and diff give you a lot of information to track down a problem. For example:

AssertionError: 'Year' != 'Years'
- Year
+ Years
?     +

Your output comes first, and the output that the test expects is second.

AssertionError: ‘Year’ != ‘Years’

Your output: Year does not equal what’s expected: Years

This is called a diff, and it shows you the differences between two files or blocks of code:

- Year
+ Years
?     +

- Dash indicates the incorrect output
+ Plus shows what it should be
? The Question mark line indicates the place of the character that’s different between the two lines. Here a + is placed under the missing s .

Here’s another example:

E       AssertionError: Expected different output when calling "arithmetic_arranger()" with ["3801 - 2", "123 + 49"]
E       assert '  3801      123    \n   - 2     + 49    \n------    -----    \n' == '  3801      123\n-    2    +  49\n------    -----'
E         -   3801      123
E         +   3801      123    
E         ?                ++++
E         - -    2    +  49
E         +    - 2     + 49    
E         - ------    -----
E         + ------    -----    
E         ?                +++++

The first line is long, and it helps to view it as 2 lines in fixed width characters, so you can compare it character by character:

'  3801      123    \n   - 2     + 49    \n------    -----    \n'
'  3801      123\n-    2    +  49\n------    -----'

Again, your output is first and the expected output is second. Here it’s easy to see extra spaces or \n characters.

E         -   3801      123
E         +   3801      123    
E         ?                ++++

Here the ? line indicates 4 extra spaces at the end of a line using four + symbols. Spaces are a little difficult to see this way, so it’s useful to use both formats together.

I hope this helps interpret your error!

1 Like

idk if that helps or not but i had some issues trying to get the last few parts of the test to pass also here is a post I created a few days ago.

THANK YOU this taught me to stare at code and tinker until it works. wow