Python - Kivy: AttributeError: 'super' object has no attribute '__getattr__' when trying to get self.ids
Let's look at the output:
'super' object has no attribute '__getattr__'
In kv language id
is set in a special way(up to 1.9.2 now), its value is not a string, because it's not a casual variable. You can't access it with <widget>.id
.
I'd say it's similar to canvas
, which is not a widget, yet it may look like that(which is why I was confused by your code :P). You've already noticed something: <some object>
is like Python's something = <object>
and that's (at least what I think) is the whole point of id
's value not being a string(which to some is odd). If id
was a string, there'd probably be needed a check to exclude it somehow from casual assigning values. Maybe it's because of performance or just simplicity.
Therefore let's say id
is a keyword for a future keyword. In fact, it is, because the characters assigned to id
will become a string key with a value of object got from WeakProxy, to the object WeakProxy points to. Or better said:
id: value
becomes
<some_root_widget>.ids[str(value)] = weakref.proxy(value)
where value
becomes an object(what print(self)
would return)
I suspect(not sure) that if you use string as the value for id
, you'll end up with weakref / WeakProxy pointing to a string. I use the word point
as it reminds me pointers, don't get confused with C pointers.
Now if you look again at the output:
super
gives you an access to a class you inherit fromprint('string id'.__getattr__)
will give you the same error, but'super'
is substituted with the real value, because well... it doesn't have__getattr__
Therefore if you assign a string value to id
, you'll get into this situation:
<some_root_widget>.ids[str('value')] = weakref.proxy('value') # + little bit of magic
Although str('value')
isn't necessarily wrong, by default you can't create weakref.proxy for a string. I'm not sure how Kivy handles this with WeakProxies, but if you assign a string to id
, roughly this is what you get.
(Please correct me if I'm wrong)
gramsch
Updated on June 14, 2022Comments
-
gramsch almost 2 years
I wrote a code for a kind of android lock thing, whenever I try to get an specific ClickableImage using the id it raises the following error:
AttributeError: 'super' object has no attribute '__getattr__'
I've spent hours trying to look for a solution for this problem, I looked other people with the same issue, and people told them to change the site of the builder, because it needed to be called first to get the ids attribute or something like that, but everytime I move the builder, it raises the error "class not defined". Any clues?
Here is my code:
from kivy.app import App from kivy.config import Config from kivy.lang import Builder from kivy.graphics import Line from kivy.uix.screenmanager import ScreenManager, Screen from kivy.uix.widget import Widget from kivy.uix.image import Image from kivy.uix.floatlayout import FloatLayout from kivy.uix.behaviors import ButtonBehavior #Variables cords = () bld = Builder.load_file('conf.kv') class Manager(ScreenManager): pass class Principal(Screen): pass class ClickableImage(ButtonBehavior, Image): def on_press(self): self.source = 'button_press.png' def on_release(self): self.source = 'button.png' self.ids.uno.source = 'button_press.png' class canva(Widget): def on_touch_down(self, touch): global cords with self.canvas: touch.ud['line'] = Line(points=(touch.x, touch.y), width=1.5) cords = (touch.x, touch.y) def on_touch_move(self,touch): global cords touch.ud['line'].points = cords + (touch.x, touch.y) def on_touch_up(self,touch): self.canvas.clear() class Api(App): def build(self): return bld if __name__ == '__main__': Api().run()
and here is my .kv file:
# conf to file: test.py <Manager>: Principal: <Principal>: GridLayout: size_hint_x: 0.5 size_hint_y: 0.6 width: self.minimum_width cols: 3 ClickableImage: id: 'uno' size: 10,10 source: 'button.png' allow_strech: True ClickableImage: id: 'dos' size: 30,30 source: 'button.png' allow_strech: True canva: