Ok, this is quite a weird case.
TL;DR
Why (and how is it Pythonically possible that) Blender's nodes dont have the
__dict__attribute.How to programatically add attributes to them without this attribute. (No, I am not going to use
exec(), thank you very much. The incoming data is royally untrusted.)
First problem
I am trying to deserialize a bunch of nodes that I previously saved to JSON. I have one somewhat working solution to this, but it involves exec(). The basic idea is that I have an assignment written like this into JSON:
"a":b
Which should as the file is read become:
<reference to newly created node>.a = b
However I don't want to run the actual thing for security reasons, so what I actually want to do is this:
- Add the field
ato the node - Assign the field to whatever
bis. (B is always a litteral value)
So, naively I tried this:
<reference to the node>.__dict__[a] = b
Python didn't like it:
'ShaderNodeMixRGB' object has no attribute '__dict__'
Yet when running dir() on the node, '__dict__' shows up. As the very first result, to be exact.
I find all this very puzzling: I didn't even know an object in Python can exist without a __dict__ attribute. Now I know the nodes are some kind of twisted wrapper around C and in some cases the very C is a wrapper around OSL. But still?
Nevertheless, I continued my search. Trying a static assignment on the node didn't work. (By this I mean <reference to the node>.foo = "bar". It seems to be blocked by __slots__. A simmilar assignment worked in the code with the exec(). And I honestly can't say why.
At this point I started thinking something was terribly wrong with my machine. I switched over to another, which had:
- A different processor architechture
- A different operating system
- A different version of Blender (the first thing was with an unstable one)
but still it had the same problem. Thinking some external factor had changed, I tried the old code. And it worked.
So what is going on?
Second problem
One may set an attribute's attribute's value (<reference to node>.inputs["foobar"] = "baz" being the most common case) in the file. This works like a charm on the exec()-based version. However, I don't see how I could make this work withous exec().
setattr(node_reference, 'property_name', property_value)should be the nonexec()equivalent. We use it in Sverchok to import / export node trees as.json( see https://github.com/nortikin/sverchok/blob/master/utils/sv_IO_panel_tools.py ) – zeffii Oct 18 '15 at 07:13__dict__- read about__slots__– sambler Oct 19 '15 at 13:24