Build a Budget App - Build a Budget App

Tell us what’s happening:

Failing test 23, console output looks like my output matches the expected value. I tested the length lines printed below the chart, they’re all the same. It says 1 test OK, but then has error messages that I don’t understand. Any guidance is appreciated.

[Warning] n (python-test-evaluator.js, line 2)
[Warning] - t+ t ? ++ (python-test-evaluator.js, line 2)
[Warning] : Expected different category names written vertically below the bar. Check that all spacing is exact. (python-test-evaluator.js, line 2)

Your code so far

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

    def deposit(self, amount, description=''):
        self.ledger.append({'amount': amount, 'description': description})

    def withdraw(self, amount, description=''):
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': description})
            return True
        return False

    def check_funds(self, amount):
        if amount > self.get_balance():
            return False
        return True

    def get_balance(self):
        balance = 0
        for tx in self.ledger:
            balance += tx['amount']
        return balance

    def transfer(self, amount, other):
        if self.check_funds(amount):
            self.ledger.append({'amount': -amount, 'description': f'Transfer to {other.name}'})
            other.ledger.append({'amount': amount, 'description': f'Transfer from {self.name}'})
            return True
        return False

    def __str__(self):
        print_string = ''
        available_width = 30 - len(self.name)
        padding_left = available_width//2
        padding_right = 30 - len(self.name) - padding_left
        print_string += f"{('*' * padding_left)}{self.name}{('*' * padding_right)}\n"
        for tx in self.ledger:
            description = tx['description'][:23]
            amount = f"{tx['amount']:.2f}".rjust(7)
            print_string += f"{description.ljust(23)}{amount}\n"
        print_string +=f"Total: {self.get_balance()}"
        return print_string

def create_spend_chart(categories):
#    print('Percentage spent by category')
    chart = 'Percentage spent by category\n'
    y_labels = [n for n in range(100, -1, -10)]
    withdrawals = []
    denominator = 0
    for category in categories:
        wd = 0
        for tx in category.ledger:
            if (tx['amount'] < 0):
                wd -= tx['amount']
        withdrawals.append((category.name, wd))
        denominator += wd
    percentages = []
    for item in withdrawals:
        percentage = (item[1]/denominator)*100
        rounded_down = percentage//10 * 10
        percentages.append(rounded_down)
    for y in y_labels:
        line = f"{y}| ".rjust(5)
        for percent in percentages:
            if percent >= y:
                line +="o  "
            else:
                line +="   "
#        print(line)
        chart += line + '\n'
#    print(f"    --{'---' * (len(categories) - 1)}--")
    chart += f"    --{'---' * (len(categories) - 1)}--\n"
    max_length = max(len(cat.name) for cat in categories)
    for i in range(max_length):
        line = "     "
        for category in categories:
            if i < len(category.name):
                line += f"{category.name[i]}  "
            else:
                line += "   "
#        print(f"{line} length of line: {len(line)}")
        chart += line + '\n'
    chart = chart.rstrip()
    return chart


food = Category('Food')
clothing = Category('Clothing')
auto = Category('Auto')
food.deposit(700)
food.withdraw(645)
clothing.deposit(300)
clothing.withdraw(255)
auto.deposit(140)
auto.withdraw(100)
print(create_spend_chart([food, clothing, auto]))


Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.1 Safari/605.1.15 Ddg/26.1

Challenge Information:

Build a Budget App - Build a Budget App

Here is the error you should look at:

AssertionError: 
'Perc[362 chars]           m  \n           e  \n           n  \n           t' != 
'Perc[362 chars]           m  \n           e  \n           n  \n           t  '

The 362 Chars means it’s skipping 362 characters that match, the problem is the end.

The assertion error and diff gives 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!

Thank you for the detailed examples. I’m having trouble understanding though: the line with the error is showing this:
[Warning] - t+ t ? ++ (python-test-evaluator.js, line 2)
[Warning] : Expected different chart representation. Check that all spacing is exact. (python-test-evaluator.js, line 2)

I think this is saying there’s only one space after my final t but there should be two? But I tested the code by replacing the spaces after the category[i] with asterisks, and the output shows there are two after the final t. Am I misinterpreting the error line?

Maybe this one is more clear,

AssertionError: 
'Perc[362 chars]           m  \n           e  \n           n  \n           t' != 
'Perc[362 chars]           m  \n           e  \n           n  \n           t  '

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

Thank you for engaging with me on this and helping me understand.

I’m not seeing how the assertion message corresponds to my code/output. I changed my code to put back the asterisks in the spaces so you can see I’ve got the spacing right, but the assertion error says there should be an apostrophe after the final t? And that I have t’ versus what it wants t ‘? The actual message doesn’t reference the apostrophe:
t+ t ? ++

And here’s my output with the asterisks:


 B**F**E**
 u**o**n**
 s**o**t**
 i**d**e**
 n*****r**
 e*****t**
 s*****a**
 s*****i**
 ******n**
 ******m**
 ******e**
 ******n**
 ******t**

How did you generate this output with asterisk?

If I modify your code like this:

return chart.replace(" ", "*")

This is the output:

Percentage*spent*by*category
100|**********
*90|**********
*80|**********
*70|**********
*60|*o********
*50|*o********
*40|*o********
*30|*o********
*20|*o**o*****
*10|*o**o**o**
**0|*o**o**o**
****----------
*****F**C**A**
*****o**l**u**
*****o**o**t**
*****d**t**o**
********h*****
********i*****
********n*****
********g

You can see it’s missing some spaces at the bottom to square off the chart.

That’s what this error means.

AssertionError: 
'Perc[362 chars]           m  \n           e  \n           n  \n           t' != 
'Perc[362 chars]           m  \n           e  \n           n  \n           t  '

Your output is missing 2 spaces at the end.

If I highlight the example you can see there are spaces at the bottom line to line up with the edge

I think I understand what you’re saying. Here is how I replaced the spaces with asterisks, and I believe this shows that the two spaces after the final “t” in the test case are there, so I’m still unclear on how to resolve this error. (I couldn’t insert formatted text in this reply so am including a screenshot of my output with the asterisks.)

 max_length = max(len(cat.name) for cat in categories)

    for i in range(max_length):

        line = "     "

for category in categories:

if i < len(category.name):

                line += f"{category.name\[i\]}\*\*"

else:

                line += "\*\*\*"

I also added a test showing the length of each of the lines with the category name printed vertically which shows they’re the same:

Can you explain this in words?

I simply replaced all spaces with asterisk in the return and it shows missing spaces.

It looks like you are hard coding a specific number of stars? What if the category names change?

I’m not sure what else to tell you but the error shows that you are missing spaces at the end.

Wrap text in triple backticks for code or fixed width

I’ve edited your post to improve the readability of the code. When you enter a code block into a forum post, please precede it with three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add the backticks.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

My code inserts two blank spaces after the i-th letter of the category name, or three spaces if the category doesn’t have a letter in the i-th position:

   max_length = max(len(cat.name) for cat in categories)

    for i in range(max_length):

        line = "     "

for category in categories:

if i < len(category.name):

                line += category.name\[i\] + "  "

else:

                line += "   "

print(f"{line} length of line: {len(line)}”)

The final print line demonstrates that each line is the same length, ie it includes the 2 spaces after the i-th position category-name-letter. I understand what you’re saying, but it seems like there’s some discrepancy in your test and my actual output/return. How do I proceed?

B  F  E   length of line: 14
u  o  n   length of line: 14
s  o  t   length of line: 14
i  d  e   length of line: 14
n     r   length of line: 14
e     t   length of line: 14
s     a   length of line: 14
s     i   length of line: 14
n   length of line: 14
m   length of line: 14
e   length of line: 14
n   length of line: 14
t   length of line: 14

I’ve edited your post to improve the readability of the code. When you enter a code block into a forum post, please precede it with three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add the backticks.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

Have you updated this? Please share your full updated code.

Or you can update your return line like this

return chart.replace(" ", "*")

I updated my return line as you show, and as you demonstrated, it returns showing the missing two final spaces. But I’m really confused, because when I add the line checking the length of the lines with the vertically-printed category names, they’re all the same length (14 characters) which includes the final two spaces. Something seems to be glitching! By the way, when I click the ‘preformatted text’ icon, it doesn’t seem to work. I’ll try editing the post after I submit it.

max_length = max(len(cat.name) for cat in categories)

for i in range(max_length):

    line = "     "
for category in categories:
if i < len(category.name):
            line += category.name\[i\] + "  "
else:
            line += "   "
print(f"{line} length of line: {len(line)}")

Please don’t wrap each line individually in code blocks.

This is not valid indentation for Python

As I mentioend, the preformatted text icon isn’t working for me so I tried to kluge it. In any case, I figured it out – my rstrip() was removing the final two spaces as well as the newline character, I fixed it and was able to pass the 2 final tests. Thanks to both of you for working through this with me.

I would not assume this. This is a pretty battle-tested lab and just calling a glitch prevents you from investigating further.

Can you share your full current code and I can look deeper into it?

Try this button, make sure the M is highlighted

Thank you again for slogging through this with me. I found the mistake, it was of course a user-error, it’s just that neither of us focused on the rstrip() statement that was causing the problem. All fixed now!

1 Like