Frame nodes in a node group

I’ve got a few nodes inside a node group I want to frame.

I’ve tried this code, and a lot of variants:

        bpy.context.area.ui_type = 'ShaderNodeTree'
        bpy.ops.node.group_edit(exit=False)
        color_node.select = True
        opacity_node.select = True
        mix_layer_node = True
        bpy.ops.node.join()
        bpy.context.area.ui_type = 'VIEW_3D'

But I continually get “context is incorrect” errors.

I believe I need to start editing the node group before I try to frame the selected nodes, but I can’t figure out how to do this in Python.

anyone know how to do this?

Looking into the c source code for Blender the operator for joining seems to poll ‘ED_operator_node_editable’ although I’m not sure what really makes a node meet these requirements.

I found that clicking on the shader node window before calling the function that creates and joins nodes makes the function work.

Below is the c code for the operator.

void NODE_OT_join(wmOperatorType *ot)
{
  /* identifiers */
  ot->name = "Join Nodes";
  ot->description = "Attach selected nodes to a new common frame";
  ot->idname = "NODE_OT_join";

  /* api callbacks */
  ot->exec = node_join_exec;
  ot->poll = ED_operator_node_editable;

  /* flags */
  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
    print("Context Before: " + str(context.area.type) + " - " + str(context.area.ui_type) + " - " + str(context.region) + " - " + str(context.space_data))

    previous_area = context.area.type
    previous_ui = context.area.ui_type
    context.area.type = 'NODE_EDITOR'
    context.area.ui_type = 'ShaderNodeTree'
    
    # Deselect all nodes.
    bpy.ops.node.select_all(action='DESELECT')

    # Select the channel node and edit it.
    material_nodes.active = channel_node
    channel_node.select = True
    bpy.ops.node.group_edit()

    # Deselect all nodes in the group.
    bpy.ops.node.select_all(action='DESELECT')

    # Select layer nodes.
    layer_nodes = get_layer_nodes(self, context, 0)
    for node in layer_nodes:
        node.select = True

    # Join layer nodes.
    frame = bpy.ops.node.join()

    print("Context After: " + str(context.area.type) + " - " + str(context.area.ui_type) + " - " + str(context.region) + " - " + str(context.space_data))

    bpy.ops.node.group_edit()
    context.area.ui_type = previous_ui
    context.area.type = previous_area

The code above throws a context is incorrect error the first time it’s called. If I continue past the error the code works as expected and creates frames around selected nodes. It seams the context is only incorrect on the initial call.