Access PythonNode

Hi all,
I would like to access a Python node and re-write the boilerplate script it has per default.
I can retrieve the node from the model filter by type in this way.

dynamoViewModel.Model.CurrentWorkspace.Nodes.Where(node => node.NodeType == "PythonScriptNode");

But to access the ‘Script’ property I need to cust the nodes ad PythonNode that is a class in the PythonNodeModels.dll that is not provided by the different Dynamo packages.
You could say, just reference that dll from the folder nodes inside Dynamo, but this means I need to remember to change this manually, all the time I am going to update the NuGet packages.
So, I am thinking if there is another way that I don’t see to access this component.
I am sure @john_pierson, you will have some good advice :slight_smile:

Thanks, heaps!!

Follow this with Dynamo CLOSED.
https://primer.dynamobim.org/10_Custom-Nodes/10-6_Python-Templates.html

1 Like

Thanks @SeanP
I was aware of this solution, but I have not considered it because I should provide the file in a shared folder and ask to do the steps, even if are simple, to a very large group, and having the file in a shared folder is not ideal.

What we have done is pushed (by IT) a modified version of the XML file that sets the custom path to a network location. This way you only have to update one .py file and everyone gets it.

The problem you will run into with trying to change / update the information at runtime is that any changes made while Dynamo is running don’t stick and most often are overwritten when Dynamo closes.

Yep, @SeanP is the alternative I was thinking and thanks for the information, very useful!!

1 Like

The hacky solution is setting the Script value using reflection.

PropertyInfo property = pythonNode.GetType().GetProperty("Script");
property.SetValue(pythonNode, Convert.ChangeType(_boilerPlate, property.PropertyType));

I have a .py file with the boilerplate that is read and passed to the property.
I tested saving the definition and re-open it and no problems with overwriting.
In this way, I’ll leave to the user the decision of using the boilerplate when needed.

Thanks again, @SeanP

1 Like

I think you can use the setter directly
set_boiterplate_python

import clr

clr.AddReference('DynamoCore')
clr.AddReference('DynamoRevitDS')
import Dynamo 
from Dynamo.Graph.Workspaces import *
from Dynamo.Graph.Nodes import *

#access to the current Dynamo instance and workspace
dynamoRevit = Dynamo.Applications.DynamoRevit()
engine = dynamoRevit.RevitDynamoModel.EngineController
currentWorkspace = dynamoRevit.RevitDynamoModel.CurrentWorkspace

clr.AddReference('PythonNodeModels')
from PythonNodeModels import *

boilerPlate = IN[0]
#find the specific node
for node in currentWorkspace.Nodes:
	if "Test" in node.Name and node.NodeType == "PythonScriptNode":
		node.IsFrozen = True
		node.Script = boilerPlate

Yeah, true only difference is that I am calling an event via a custom toolbar menu, so to access the node, or I use reflection or I need to reference the .dll as I mentioned previously.
Writing in C# and using reflection I did exactly what you did using IronPython :slight_smile:
Thanks for your message.

1 Like