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()
The error was due to assigning string value to id
in kv file.
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'
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()