Search code examples
pythonpython-3.xkivykivy-languagepython-sockets

'super' object has no attribute '__getattr__' kivy


I am writing a chat app using kivy and socket. However, whenever my app receives a message, I will always get an AttributeError: 'super' object has no attribute '__getattr__'.

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivymd.dialog import MDDialog
from kivymd.theming import ThemeManager
from kivymd.navigationdrawer import NavigationLayout
from kivymd.list import OneLineAvatarListItem, ILeftBody
from kivymd.toast import toast
from kivymd.dialog import MDDialog
from kivy.uix.popup import Popup
from threading import Thread

import socket


sock = socket.socket()
sock.connect(('127.0.0.1', 6718))
sock.sendall(b"add_contact hello llo")

sock = socket.socket()
sock.connect(('127.0.0.1', 6718))

sock.sendall(b'new llo')


class MyLayout(BoxLayout):
    scr_mngr = ObjectProperty(None)

    def check_data_login(self):
        username = self.scr_mngr.screen1.username.text
        password = self.scr_mngr.screen1.password.text

        print(username)
        print(password)
        if username == "KivyMD" and password == "kivy":
            self.ids["wrongpass"].text = ""
            self.change_screen("screen2")
        else:
            self.ids["wrongpass"].text = "Wrong username or password, please try again"

    def change_screen(self, screen, *args):
        self.scr_mngr.transition.direction = 'left'
        self.scr_mngr.current = screen

    def back_to_chat(self):
        self.scr_mngr.transition.direction = 'right'
        self.scr_mngr.current = 'screen2'


class nav_layout(NavigationLayout):
    def print_text(self):
        print('hello')

    def check_data_login(self):
        username = self.ids.screen1.username.text
        password = self.ids.screen1.password.text

        print(username)
        print(password)
        if username == "KivyMD" and password == "kivy":
            self.change_screen("screen2")
            self.ids.wrongpass.text = ""
        else:
            self.ids.wrongpass.text = \
                "Wrong username or password, please try again"

    def change_screen(self, screen, *args):
        self.ids.scr_mngr.transition.direction = 'left'
        self.ids.scr_mngr.current = screen

    def back_to_chat(self):
        self.ids.scr_mngr.transition.direction = 'right'
        self.ids.scr_mngr.current = 'screen2'

    def logout(self):
        # logout function, returns to screen 1
        self.ids.scr_mngr.current = 'screen1'
    def oof(self, data):
        self.ids.Chat_String.text = data
class UploadPopup(Popup):
    def load(self, path, selection):
        print(path, selection) 


KV = """
#:import Toolbar kivymd.toolbar.Toolbar
#:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
#:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar
#:import MDTextField kivymd.textfields.MDTextField
#:import MDSeparator kivymd.card.MDSeparator
#:import MDThemePicker kivymd.theme_picker.MDThemePicker
#:import CardTransition kivy.uix.screenmanager.CardTransition
#:import Factory kivy.factory.Factory


<MDCustomIconItem>:
    text: root.text

    AvatarSampleWidget:
        source: root.icon

<UploadPopup>:
    id: popup
    title: "Upload"
    BoxLayout:
        FileChooserIconView:
            id: FileChoose
            pos_hint_x: 0.5
            pos_hint_y: 0.5
            on_selection: root.load(FileChoose.path, FileChoose.selection)
        MDRaisedButton:
            text: "Upload"
            text_color: (0,0,0,1)
            on_release: root.load(FileChoose.path, FileChoose.selection)
            on_release: popup.dismiss()

        MDRaisedButton:
            text: "Close"
            text_color: (0,0,0,1)
            on_release: popup.dismiss()


nav_layout:
    id: nav_layout
    MDNavigationDrawer:
        id: nav_drawer
        drawer_logo: 'logo.png'
        NavigationDrawerToolbar:
            title: 'hello'
        NavigationDrawerIconButton:
            icon: 'settings'
            text: 'Account Settings'
            on_release: root.change_screen('screen3')
        NavigationDrawerIconButton:
            icon: 'face'
            text: 'Friends'
            on_release: root.print_text()
        NavigationDrawerIconButton:
            icon: 'logout'
            text: 'Logout'
            on_release: root.logout()
        NavigationDrawerDivider:
            height: dp(1)
    MyLayout:
        scr_mngr: scr_mngr
        orientation: 'vertical'


        ScreenManager:

            transition: CardTransition()
            id: scr_mngr
            screen1: screen1

            Screen:
                id: screen1
                name: 'screen1'
                username: username
                password: password

                BoxLayout:
                    size_hint: None, None
                    size: dp(520), dp(340)
                    pos_hint: {'center_x': 0.5, 'center_y': 0.5}

                    BoxLayout:
                        orientation:'vertical'
                        padding: dp(20)
                        spacing:20

                        MDLabel:
                            text: 'Chat App'
                            theme_text_color: 'Secondary'
                            font_style:"Title"
                            size_hint_y: None
                            height: dp(36)

                        MDSeparator:
                            height: dp(1)

                        MDTextField:
                            id: username
                            hint_text: "Username "
                            size_hint_y: 0.9
                            helper_text_mode: "on_focus"

                        MDTextField:
                            id: password
                            hint_text: "Password "
                            helper_text_mode: "on_focus"
                            size_hint_y: 0.9
                            password: True

                        MDFlatButton:
                            text: "Login"
                            pos_hint: {'center_x': 0.5}
                            on_release: root.check_data_login()

                        MDLabel:
                            id: wrongpass
                            color: 1,0,1,1
                            text: ""



            Screen:
                name: 'screen2'
                id: screen2

                Toolbar:
                    id: toolbar
                    title: "Welcome ! "
                    pos_hint: {'center_x': 0.5, 'center_y': 0.96}
                    md_bg_color: app.theme_cls.primary_color
                    background_palette: 'DeepPurple'
                    background_hue: 'A400'
                    left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
                    right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]

                MDLabel:
                    font_style: 'Title'
                    theme_text_color: 'Primary'
                    text: "Data :"
                    height: self.texture_size[1] + dp(3)
                    halign: 'center'
                    pos_hint: {'center_x': 0.5, 'center_y': 0.5}



            Screen:
                name: 'screen3'
                id: 'screen3'

                Toolbar:
                    id: tools
                    title: "Your Profile"
                    pos_hint: {'center_x': 0.5, 'center_y': 0.96}
                    md_bg_color: app.theme_cls.primary_color
                    background_palette: 'DeepPurple'
                    background_hue: 'A400'
                    left_action_items: [['arrow-left', lambda x: root.back_to_chat()]]
                MDLabel:
                    id: 'Profile_String'
                    font_size: 90
                    text: "XXX"
                    halign: 'center'
                    pos_hint: {'center_x': 0.5, 'center_y': 0.85}

            Screen:
                name: 'screen4'
                id: 'screen4'

                Toolbar:
                    id: tools
                    title: "XXX"
                    pos_hint: {'center_x': 0.5, 'center_y': 0.96}
                    md_bg_color: app.theme_cls.primary_color
                    background_palette: 'DeepPurple'
                    background_hue: 'A400'
                    left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
                    right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]
                ScrollView:
                    pos_hint: {'center_x': .55, 'y': .35}
                    MDLabel:
                        id: 'Chat_String'
                        font_size: 40
                        text: "XXX"


                MDTextField:
                    id: 'Input_String'
                    hint_text: 'Enter Your Message...'
                    helper_text_mode: 'on_focus'
                    pos_hint: {'center_x': 0.35, 'center_y': 0.2}
                    size_hint_x: 0.6
                    multiline: True


                MDRaisedButton:
                    id: 'Send_Button'
                    text: 'Send'
                    pos_hint: {'center_x': 0.75, 'center_y': 0.2}

                MDRaisedButton:
                    id: 'Choose_Image'
                    text: 'Attach File'
                    pos_hint: {'center_x': 0.9, 'center_y': 0.2}
                    on_release: Factory.UploadPopup().open()
"""


class MDCustomIconItem(OneLineAvatarListItem):
    icon = StringProperty('')
    text = StringProperty()

    def _set_active(self, active, list):
        pass


class AvatarSampleWidget(ILeftBody, Image):
    pass


class MyApp(App):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    title = "Navigation Drawer"
    main_widget = None
    def __getattr__(self, attr):
        return super().__getattr__(attr)
    def build(self):
        self.main_widget = Builder.load_string(KV)
        return self.main_widget

    def callback(self, instance, value):
        self.main_widget.ids.scr_mngr.current = 'screen4'

    def recover_data(self):
        print('started')
        while True:
            data = sock.recv(1024)
            data = data.decode()
            if data:
                print(data)
                data = data.split()
                data = data[-1] + ": " + ' '.join(data[:-1])
                r = data + '\n'
                open('chat1.txt', 'a+').write(r)
                e = open('chat1.txt', 'r').readlines()
                nav_layout().oof('\n\r'.join(e))
                print(data)

    def on_start(self):
        Thread(target=self.recover_data).start()
        for i in range(15):
            self.main_widget.ids.nav_drawer.add_widget(
                MDCustomIconItem(
                    text="Item menu %d" % i,
                    icon='logo.png',
                    on_release=lambda x, y=i: self.callback(x, y)))


MyApp().run()

I know this question has been asked before multiple times on StackOverflow, but none of them solved my problem.
Any help will be appreciated, Thank You!

**Edit: ** My full error message is here

Exception has occurred: AttributeError
'super' object has no attribute '__getattr__'
  File "/Users/grace/Desktop/Android_APP/kivy/properties.pyx", line 841, in kivy.properties.ObservableDict.__getattr__
  File "/Users/grace/Desktop/Android_APP/app.py", line 81, in oof
    self.ids.Chat_String.text = data
  File "/Users/grace/Desktop/Android_APP/app.py", line 334, in recover_data
    nav_layout().oof('\n\r'.join(e))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 869, in run
    del self._target, self._args, self._kwargs
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 885, in _bootstrap
    self._bootstrap_inner()

Solution

  • Reason

    The error was due to assigning string value to id in kv file.

    Solution

    Remove single quote from all id in kv file.

    Kv Language » Referencing Widgets

    When assigning a value to id, remember that the value isn’t a string. There are no quotes: good -> id: value, bad -> id: 'value'

    Example

    main.py

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.properties import ObjectProperty, StringProperty
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.image import Image
    from kivymd.dialog import MDDialog
    from kivymd.theming import ThemeManager
    from kivymd.navigationdrawer import NavigationLayout
    from kivymd.list import OneLineAvatarListItem, ILeftBody
    # from kivymd.toast import toast
    from kivymd.dialog import MDDialog
    from kivy.uix.popup import Popup
    from threading import Thread
    
    import socket
    
    
    # sock = socket.socket()
    # sock.connect(('127.0.0.1', 6718))
    # sock.sendall(b"add_contact hello llo")
    #
    # sock = socket.socket()
    # sock.connect(('127.0.0.1', 6718))
    #
    # sock.sendall(b'new llo')
    
    
    class MyLayout(BoxLayout):
        scr_mngr = ObjectProperty(None)
    
        def check_data_login(self):
            username = self.scr_mngr.screen1.username.text
            password = self.scr_mngr.screen1.password.text
    
            print(username)
            print(password)
            if username == "KivyMD" and password == "kivy":
                self.ids["wrongpass"].text = ""
                self.change_screen("screen2")
            else:
                self.ids["wrongpass"].text = "Wrong username or password, please try again"
    
        def change_screen(self, screen, *args):
            self.scr_mngr.transition.direction = 'left'
            self.scr_mngr.current = screen
    
        def back_to_chat(self):
            self.scr_mngr.transition.direction = 'right'
            self.scr_mngr.current = 'screen2'
    
    
    class nav_layout(NavigationLayout):
        def print_text(self):
            print('hello')
            print("self.ids.Chat_String.text=", self.ids.Chat_String.text)
    
        def check_data_login(self):
            username = self.ids.screen1.username.text
            password = self.ids.screen1.password.text
    
            print(username)
            print(password)
            if username == "KivyMD" and password == "kivy":
                self.change_screen("screen2")
                self.ids.wrongpass.text = ""
            else:
                self.ids.wrongpass.text = \
                    "Wrong username or password, please try again"
    
        def change_screen(self, screen, *args):
            self.ids.scr_mngr.transition.direction = 'left'
            self.ids.scr_mngr.current = screen
    
        def back_to_chat(self):
            self.ids.scr_mngr.transition.direction = 'right'
            self.ids.scr_mngr.current = 'screen2'
    
        def logout(self):
            # logout function, returns to screen 1
            self.ids.scr_mngr.current = 'screen1'
    
        def oof(self, data):
            self.ids.Chat_String.text = data
    
    
    class UploadPopup(Popup):
        def load(self, path, selection):
            print(path, selection)
    
    
    KV = """
    #:import Toolbar kivymd.toolbar.Toolbar
    #:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
    #:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
    #:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
    #:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar
    #:import MDTextField kivymd.textfields.MDTextField
    #:import MDSeparator kivymd.card.MDSeparator
    #:import MDThemePicker kivymd.theme_picker.MDThemePicker
    #:import CardTransition kivy.uix.screenmanager.CardTransition
    #:import Factory kivy.factory.Factory
    
    
    <MDCustomIconItem>:
        text: root.text
    
        AvatarSampleWidget:
            source: root.icon
    
    <UploadPopup>:
        id: popup
        title: "Upload"
        BoxLayout:
            FileChooserIconView:
                id: FileChoose
                pos_hint_x: 0.5
                pos_hint_y: 0.5
                on_selection: root.load(FileChoose.path, FileChoose.selection)
            MDRaisedButton:
                text: "Upload"
                text_color: (0,0,0,1)
                on_release: root.load(FileChoose.path, FileChoose.selection)
                on_release: popup.dismiss()
    
            MDRaisedButton:
                text: "Close"
                text_color: (0,0,0,1)
                on_release: popup.dismiss()
    
    
    nav_layout:
        id: nav_layout
        MDNavigationDrawer:
            id: nav_drawer
            drawer_logo: 'logo.png'
            NavigationDrawerToolbar:
                title: 'hello'
            NavigationDrawerIconButton:
                icon: 'settings'
                text: 'Account Settings'
                on_release: root.change_screen('screen3')
            NavigationDrawerIconButton:
                icon: 'face'
                text: 'Friends'
                on_release: root.print_text()
            NavigationDrawerIconButton:
                icon: 'logout'
                text: 'Logout'
                on_release: root.logout()
            NavigationDrawerDivider:
                height: dp(1)
        MyLayout:
            scr_mngr: scr_mngr
            orientation: 'vertical'
    
    
            ScreenManager:
    
                transition: CardTransition()
                id: scr_mngr
                screen1: screen1
    
                Screen:
                    id: screen1
                    name: 'screen1'
                    username: username
                    password: password
    
                    BoxLayout:
                        size_hint: None, None
                        size: dp(520), dp(340)
                        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
    
                        BoxLayout:
                            orientation:'vertical'
                            padding: dp(20)
                            spacing:20
    
                            MDLabel:
                                text: 'Chat App'
                                theme_text_color: 'Secondary'
                                font_style:"Title"
                                size_hint_y: None
                                height: dp(36)
    
                            MDSeparator:
                                height: dp(1)
    
                            MDTextField:
                                id: username
                                hint_text: "Username "
                                size_hint_y: 0.9
                                helper_text_mode: "on_focus"
    
                            MDTextField:
                                id: password
                                hint_text: "Password "
                                helper_text_mode: "on_focus"
                                size_hint_y: 0.9
                                password: True
    
                            MDFlatButton:
                                text: "Login"
                                pos_hint: {'center_x': 0.5}
                                on_release: root.check_data_login()
    
                            MDLabel:
                                id: wrongpass
                                color: 1,0,1,1
                                text: ""
    
    
    
                Screen:
                    name: 'screen2'
                    id: screen2
    
                    Toolbar:
                        id: toolbar
                        title: "Welcome ! "
                        pos_hint: {'center_x': 0.5, 'center_y': 0.96}
                        md_bg_color: app.theme_cls.primary_color
                        background_palette: 'DeepPurple'
                        background_hue: 'A400'
                        left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
                        right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]
    
                    MDLabel:
                        font_style: 'Title'
                        theme_text_color: 'Primary'
                        text: "Data :"
                        height: self.texture_size[1] + dp(3)
                        halign: 'center'
                        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
    
    
    
                Screen:
                    name: 'screen3'
                    id: screen3
    
                    Toolbar:
                        id: tools
                        title: "Your Profile"
                        pos_hint: {'center_x': 0.5, 'center_y': 0.96}
                        md_bg_color: app.theme_cls.primary_color
                        background_palette: 'DeepPurple'
                        background_hue: 'A400'
                        left_action_items: [['arrow-left', lambda x: root.back_to_chat()]]
                    MDLabel:
                        id: Profile_String
                        font_size: 90
                        text: "XXX"
                        halign: 'center'
                        pos_hint: {'center_x': 0.5, 'center_y': 0.85}
    
                Screen:
                    name: 'screen4'
                    id: screen4
    
                    Toolbar:
                        id: tools
                        title: "XXX"
                        pos_hint: {'center_x': 0.5, 'center_y': 0.96}
                        md_bg_color: app.theme_cls.primary_color
                        background_palette: 'DeepPurple'
                        background_hue: 'A400'
                        left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer() ]]
                        right_action_items: [['animation', lambda x: MDThemePicker().open()], ['camera', lambda x: print('hello')]]
                    ScrollView:
                        id: sv
                        pos_hint: {'center_x': .55, 'y': .35}
                        MDLabel:
                            id: Chat_String
                            font_size: 40
                            text: "XXX"
    
    
                    MDTextField:
                        id: Input_String
                        hint_text: 'Enter Your Message...'
                        helper_text_mode: 'on_focus'
                        pos_hint: {'center_x': 0.35, 'center_y': 0.2}
                        size_hint_x: 0.6
                        multiline: True
    
    
                    MDRaisedButton:
                        id: Send_Button
                        text: 'Send'
                        pos_hint: {'center_x': 0.75, 'center_y': 0.2}
    
                    MDRaisedButton:
                        id: Choose_Image
                        text: 'Attach File'
                        pos_hint: {'center_x': 0.9, 'center_y': 0.2}
                        on_release: Factory.UploadPopup().open()
    """
    
    
    class MDCustomIconItem(OneLineAvatarListItem):
        icon = StringProperty('')
        text = StringProperty()
    
        def _set_active(self, active, list):
            pass
    
    
    class AvatarSampleWidget(ILeftBody, Image):
        pass
    
    
    class MyApp(App):
        theme_cls = ThemeManager()
        theme_cls.primary_palette = 'Blue'
        title = "Navigation Drawer"
        main_widget = None
    
        def __getattr__(self, attr):
            return super().__getattr__(attr)
    
        def build(self):
            self.main_widget = Builder.load_string(KV)
            return self.main_widget
    
        def callback(self, instance, value):
            self.main_widget.ids.scr_mngr.current = 'screen4'
    
        def recover_data(self):
            print('started')
            while True:
                data = sock.recv(1024)
                data = data.decode()
                if data:
                    print(data)
                    data = data.split()
                    data = data[-1] + ": " + ' '.join(data[:-1])
                    r = data + '\n'
                    open('chat1.txt', 'a+').write(r)
                    e = open('chat1.txt', 'r').readlines()
                    nav_layout().oof('\n\r'.join(e))
                    print(data)
    
        def on_start(self):
            Thread(target=self.recover_data).start()
            for i in range(15):
                self.main_widget.ids.nav_drawer.add_widget(
                    MDCustomIconItem(
                        text="Item menu %d" % i,
                        icon='logo.png',
                        on_release=lambda x, y=i: self.callback(x, y)))
    
    
    MyApp().run()
    

    Output

    KivyMD Navigation Drawer