Expressions reading a plug value from a node (A) inside another node (B), are left in a broken state if you delete (A), where they still try to read the deleted plug value.
Steps to reproduce
Create a Box, and a node inside the box
At the top level, create an expression that reads some plug from the node inside the box
Then delete the box and try to view (or serialise) the expression.
Here is an example graph you can use. Try deleting the "Box", then clicking on the expression node.
```
Traceback (most recent call last):
File "/software/apps/gaffer/0.54.2.1/cent7.x86_64/cortex/10/gaffer/python/GafferUI/Widget.py", line 937, in eventFilter
self.__showHide( qObject, qEvent )
File "/software/apps/gaffer/0.54.2.1/cent7.x86_64/cortex/10/gaffer/python/GafferUI/Widget.py", line 1004, in __showHide
widget._visibilityChangedSignal( widget )
IECore.Exception: Object "ScriptNode" is not an ancestor of "name".
```
Thanks for the simple repro Ivan. I'm inclined to close as "won't fix" for the following reasons :
We frown on connections like this that "reach inside" the internals of other nodes. They break encapsulation and make connections that are hard for the user to discover and reason about.
We plan to rewrite the Expression node so that it doesn't refer to plugs by their relative paths, which will render this bug irrelevant.
I presume it's not too hard to work around the problem by promoting the internal plug out of the box.
Let me know if you want to make the case for fixing it instead.
Version: Gaffer 0.54.2.1-linux Third-party tools: None Third-party modules: None
Description
Expressions reading a plug value from a node (A) inside another node (B), are left in a broken state if you delete (A), where they still try to read the deleted plug value.
Steps to reproduce
Here is an example graph you can use. Try deleting the "Box", then clicking on the expression node.
Example
``` import Gaffer import GafferImage import GafferScene import IECore import imath Gaffer.Metadata.registerValue( parent, "serialiser:milestoneVersion", 0, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 54, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 2, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:patchVersion", 1, persistent=False ) __children = {} __children["Box"] = Gaffer.Box( "Box" ) parent.addChild( __children["Box"] ) __children["Box"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Box"].addChild( Gaffer.ContextVariables( "ContextVariables" ) ) __children["Box"]["ContextVariables"].setup( GafferScene.ScenePlug( "in", ) ) __children["Box"]["ContextVariables"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Box"].addChild( GafferScene.Sphere( "Sphere" ) ) __children["Box"]["Sphere"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Text"] = GafferImage.Text( "Text" ) parent.addChild( __children["Text"] ) __children["Text"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Expression"] = Gaffer.Expression( "Expression" ) parent.addChild( __children["Expression"] ) __children["Expression"]["__in"].addChild( Gaffer.StringPlug( "p0", defaultValue = 'sphere', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Expression"]["__out"].addChild( Gaffer.StringPlug( "p0", direction = Gaffer.Plug.Direction.Out, defaultValue = 'Hello World', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Expression"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Box"]["__uiPosition"].setValue( imath.V2f( 7.30611849, 5.37886429 ) ) Gaffer.Metadata.registerValue( __children["Box"]["ContextVariables"]["in"], 'noduleLayout:section', 'top' ) Gaffer.Metadata.registerValue( __children["Box"]["ContextVariables"]["out"], 'noduleLayout:section', 'bottom' ) __children["Box"]["ContextVariables"]["__uiPosition"].setValue( imath.V2f( 26.8999977, -1.10000002 ) ) __children["Box"]["Sphere"]["__uiPosition"].setValue( imath.V2f( 39.9879379, -1.50000131 ) ) __children["Text"]["out"].setInput( __children["Text"]["__merge"]["out"] ) __children["Text"]["text"].setInput( __children["Expression"]["__out"]["p0"] ) __children["Text"]["area"].setValue( imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 2444, 1798 ) ) ) __children["Text"]["__uiPosition"].setValue( imath.V2f( 7.3726716, 12.8995705 ) ) __children["Expression"]["__in"]["p0"].setInput( __children["Box"]["Sphere"]["name"] ) __children["Expression"]["__uiPosition"].setValue( imath.V2f( -1.27267027, 12.9652576 ) ) __children["Expression"]["__engine"].setValue( 'python' ) __children["Expression"]["__expression"].setValue( 'var = parent["__in"]["p0"]\nparent["__out"]["p0"] = repr(var)\n' ) del __children ```
Debug log
Click to Expand
``` Traceback (most recent call last): File "/software/apps/gaffer/0.54.2.1/cent7.x86_64/cortex/10/gaffer/python/GafferUI/Widget.py", line 937, in eventFilter self.__showHide( qObject, qEvent ) File "/software/apps/gaffer/0.54.2.1/cent7.x86_64/cortex/10/gaffer/python/GafferUI/Widget.py", line 1004, in __showHide widget._visibilityChangedSignal( widget ) IECore.Exception: Object "ScriptNode" is not an ancestor of "name". ```