Ok, this is quite a weird case.
Why (and how is it Pythonically possible that) Blender's nodes dont have the
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.)
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:
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?
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