'AttributeError: 'HelloWorld' object has no attribute 'say_hello'

I'm trying to learn some python through the tutorial in beeware in order to create an app for my thesis.

I'm at the step "Update and run in one step" at tutorial 4 and I have to replace a section of my code.

I have to replace

def say_hello(self, widget):
    self.main_window.info_dialog(
        'Hello, {}'.format(self.name_input.value),
        'Hi there!'
)

with the new code

def say_hello(self, widget):
if self.name_input.value:
    name = self.name_input.value
else:
    name = 'stranger'

self.main_window.info_dialog(
    'Hello, {}'.format(name),
    'Hi there!'
)   

With the first one it works flawless but when I replace it gives me the error

Traceback (most recent call last):
File "/home/alessio/beeware-tutorial/beeware-venv/lib/python3.9/site-packages/toga_gtk/app.py", line 102, in gtk_startup
self.interface.startup() 
File "/home/alessio/beeware-tutorial/helloworld/src/helloworld/app.py", line 25, in startup
on_press=self.say_hello,
AttributeError: 'HelloWorld' object has no attribute 'say_hello'

I don't understand why and as soon as I try to modify something I get an indentation error

The entire code is

import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW


class HelloWorld(toga.App):
    def startup(self):
        main_box = toga.Box(style=Pack(direction=COLUMN))

        name_label = toga.Label(
            'Your name: ',
            style=Pack(padding=(0, 5))
        )
        self.name_input = toga.TextInput(style=Pack(flex=1))

        name_box = toga.Box(style=Pack(direction=ROW, padding=5))
        name_box.add(name_label)
        name_box.add(self.name_input)

        button = toga.Button(
            'Say Hello!',
            on_press=self.say_hello,
            style=Pack(padding=5)
        )

        main_box.add(name_box)
        main_box.add(button)

        self.main_window = toga.MainWindow(title=self.formal_name)
        self.main_window.content = main_box
        self.main_window.show()

    """def say_hello(self, widget):
        self.main_window.info_dialog(
            'Hello, {}'.format(self.name_input.value),
            'Hi there!'
    )"""
    
    
def say_hello(self, widget):
    if self.name_input.value:
        name = self.name_input.value
    else:
        name = 'stranger'

    self.main_window.info_dialog(
        'Hello, {}'.format(name),
        'Hi there!'
    )   


def main():
    return HelloWorld()


Solution 1:[1]

The sayhello function should be in the class Code:

import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW


class HelloWorld(toga.App):
    def startup(self):
        main_box = toga.Box(style=Pack(direction=COLUMN))

        name_label = toga.Label(
            'Your name: ',
            style=Pack(padding=(0, 5))
        )
        self.name_input = toga.TextInput(style=Pack(flex=1))

        name_box = toga.Box(style=Pack(direction=ROW, padding=5))
        name_box.add(name_label)
        name_box.add(self.name_input)

        button = toga.Button(
            'Say Hello!',
            on_press=self.say_hello,
            style=Pack(padding=5)
        )

        main_box.add(name_box)
        main_box.add(button)

        self.main_window = toga.MainWindow(title=self.formal_name)
        self.main_window.content = main_box
        self.main_window.show()

    """def say_hello(self, widget):
        self.main_window.info_dialog(
            'Hello, {}'.format(self.name_input.value),
            'Hi there!'
    )"""


    def say_hello(self, widget):
        if self.name_input.value:
            name = self.name_input.value
        else:
            name = 'stranger'

        self.main_window.info_dialog(
            'Hello, {}'.format(name),
            'Hi there!'
        )


def main():
    return HelloWorld()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 TheCoder1001