You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apologies if the title isn't clear, hopefully this example will explain my issue:
So I'm using aiorepl to help make certain bits of my code interactive, and I pass object.__dict__ to aiorepl.task().
What's confused me is which bits of the object I can actually modify - basically I only seem to be able to assign values to properties of sub-objects - assigning a value to a property of the top level object just results in a TypeError. In this example the only assignment that works is to inner.a
Now to run it and try to access the properties of the outerClass and innerClass objects:
Starting asyncio REPL...
--> b
NameError: name 'b' isn't defined
--> c
NameError: name 'c' isn't defined
--> d
3
--> inner
<innerClass object at 2000ba00>
--> inner.a
10
--> d = 10
TypeError:
--> inner.a = 11
--> inner.a
11
I might not be understanding __dict__ properly, but I think it would help if there was a way of making this behave a bit more intutively - ie. I'd like to pass an object (maybe wrapped in some function to pull out the relevant bits) and I can then access the object like you would at a normal python terminal - read/write access to all the properties, and can call methods.
The text was updated successfully, but these errors were encountered:
hi @sandyscott -- Interesting question! The ability to set the globals dict was mostly intended to be passed a module's dict.
In MicroPython the dictionary returned by __dict__ on a class instance is read-only. (This is different to CPython). It's not a copy, it references the underlying members dict, but it's marked as read-only.
b and c aren't available because they aren't part of the instance's __dict__ (this is the same in CPython).
Setting nested members works because it's a regular read-only lookup of the first level, then eval() is taking care of the assignment.
In theory you could construct a dict-like object (that implements __setitem__ etc) that wraps an instance type, but unfortunately in MicroPython, the dict passed to eval (used internally in aiorepl) needs to be an actual dict.
I suspect the best workaround for your use case is to make a very simple wrapper dict, i.e. aiorepl.task({"obj": obj }) which would allow you to do --> obj.d = 10 etc. Not quite so convenient but I haven't been able to think of a better workaround.
Thanks for the detailed response - after a bit more digging I realise __dict__ is somewhat more of a minefield than I'd realised. I also found a roughly equivalent workaround (wrapping it in a minimal object, then using __dict__) but your way is neater.
I'm satisfied that my problem is solved, if you or another maintainer thinks this is worth adding to the documentation, I created PR 687 which adds an extra paragraph to cover this use case.
Apologies if the title isn't clear, hopefully this example will explain my issue:
So I'm using aiorepl to help make certain bits of my code interactive, and I pass
object.__dict__
toaiorepl.task()
.What's confused me is which bits of the object I can actually modify - basically I only seem to be able to assign values to properties of sub-objects - assigning a value to a property of the top level object just results in a
TypeError
. In this example the only assignment that works is toinner.a
Now to run it and try to access the properties of the outerClass and innerClass objects:
I might not be understanding
__dict__
properly, but I think it would help if there was a way of making this behave a bit more intutively - ie. I'd like to pass an object (maybe wrapped in some function to pull out the relevant bits) and I can then access the object like you would at a normal python terminal - read/write access to all the properties, and can call methods.The text was updated successfully, but these errors were encountered: