From db3ff102ef6920442432c61432f83b4f2be73270 Mon Sep 17 00:00:00 2001 From: Roberto T Date: Tue, 17 Jun 2025 13:49:05 -0600 Subject: [PATCH 1/3] DYN-8274 PythonScript With Exception I've added a unit test that will be inserting a piece of code in the PythonScript node so a exception will be generated and will be reflected as a warning message in the node. --- .../DynamoPythonTests/PythonEditTests.cs | 37 +++++ test/core/python/withStatementTest.dyn | 154 ++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 test/core/python/withStatementTest.dyn diff --git a/test/Libraries/DynamoPythonTests/PythonEditTests.cs b/test/Libraries/DynamoPythonTests/PythonEditTests.cs index c0d3f53548f..ab3d158cabe 100644 --- a/test/Libraries/DynamoPythonTests/PythonEditTests.cs +++ b/test/Libraries/DynamoPythonTests/PythonEditTests.cs @@ -16,6 +16,8 @@ using DynCmd = Dynamo.Models.DynamoModel; using System.Threading; using PythonNodeModelsWpf; +using CoreNodeModels; + namespace Dynamo.Tests { @@ -653,6 +655,41 @@ public void Test_Hidden_Properties_Python() AssertPreviewValue(getItemAtIndex2, new string[] { "TSplineVertex", "TSplineVertex" }); } + [Test] + public void Test_With_Exception_Python() + { + //This piece of code will generate an exception in PythonScript node + var line_update = "vec = Vector.ByCordinates(10,20)"; + var warningMessageExpected = "type object 'Vector' has no attribute 'ByCordinates'"; + + // open test graph + var examplePath = Path.Combine(TestDirectory, @"core\python", @"withStatementTest.dyn"); + ViewModel.OpenCommand.Execute(examplePath); + ViewModel.HomeSpace.Run(); + + var watchNode = ViewModel.Model.CurrentWorkspace.Nodes.OfType().First(); + var pythonNode = ViewModel.Model.CurrentWorkspace.Nodes.OfType().First(); + + //Verify that the initial run get the expected value + Assert.That(watchNode.OutputData.InitialValue, Is.EqualTo("test2")); + + //Verity that don't have warnings/errors in the python node + Assert.AreEqual(pythonNode.NodeInfos.Count, 0); + + var script = pythonNode.Script; + //This replacing this text in the code will generate an exception in PythonScript node + script = script.Replace("result = \"test2\"", line_update); + + UpdatePythonNodeContent(pythonNode, script); + pythonNode.OnNodeModified(); + + //Verity that we have 1 warning in the python node + Assert.AreEqual(pythonNode.NodeInfos.Count, 1); + + //Check that the warning message expected is correct + Assert.IsTrue(pythonNode.NodeInfos.FirstOrDefault().Message.Contains(warningMessageExpected)); + } + [Test] public void CpythonRestart_ReloadsModules() { diff --git a/test/core/python/withStatementTest.dyn b/test/core/python/withStatementTest.dyn new file mode 100644 index 00000000000..db87fe8a652 --- /dev/null +++ b/test/core/python/withStatementTest.dyn @@ -0,0 +1,154 @@ +{ + "Uuid": "ff866c3d-6880-4395-9811-a7a997787fe8", + "IsCustomNode": false, + "Description": "", + "Name": "withStatementTest", + "ElementResolver": { + "ResolutionMap": {} + }, + "Inputs": [], + "Outputs": [], + "Nodes": [ + { + "ConcreteType": "PythonNodeModels.PythonNode, PythonNodeModels", + "Code": "import clr\r\nclr.AddReference('ProtoGeometry')\r\nfrom Autodesk.DesignScript.Geometry import *\r\n\r\nresult = \"\"\r\n\r\nfile1 = \"test_python_exception.txt\"\r\nwith open(file1, 'w') as f1:\r\n f1.write(\"hello world\")\r\n \r\n \r\nwith open(file1, 'a') as f2:\r\n result = \"test2\"\r\n f2.write(\"bye world\")\r\n \r\nOUT = result", + "Engine": "CPython3", + "VariableInputPorts": true, + "Id": "7ce98303309c4466a7556c8a06fb101b", + "NodeType": "PythonScriptNode", + "Inputs": [ + { + "Id": "84b66783fb8949a391137c1cb39401b0", + "Name": "IN[0]", + "Description": "Input #0", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "67ed422c9a7742bb9223621da7e98c4a", + "Name": "OUT", + "Description": "Result of the python script", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Runs an embedded Python script." + }, + { + "ConcreteType": "CoreNodeModels.Watch, CoreNodeModels", + "WatchWidth": 58.0, + "WatchHeight": 40.0, + "Id": "afc3a4351a094217b05d451681fd8092", + "NodeType": "ExtensionNode", + "Inputs": [ + { + "Id": "3c2cba04d3064ef5b163a3135557fa01", + "Name": "", + "Description": "Node to show output from", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "d4872cc557224739b2636312dc29ca58", + "Name": "", + "Description": "Node output", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Visualizes a node's output" + } + ], + "Connectors": [ + { + "Start": "67ed422c9a7742bb9223621da7e98c4a", + "End": "3c2cba04d3064ef5b163a3135557fa01", + "Id": "d263af62b2b547d39c88d6cd468f5c0a", + "IsHidden": "False" + } + ], + "Dependencies": [], + "NodeLibraryDependencies": [], + "EnableLegacyPolyCurveBehavior": true, + "Thumbnail": "", + "GraphDocumentationURL": null, + "ExtensionWorkspaceData": [ + { + "ExtensionGuid": "28992e1d-abb9-417f-8b1b-05e053bee670", + "Name": "Properties", + "Version": "3.6", + "Data": {} + } + ], + "Author": "", + "Linting": { + "activeLinter": "None", + "activeLinterId": "7b75fb44-43fd-4631-a878-29f4d5d8399a", + "warningCount": 0, + "errorCount": 0 + }, + "Bindings": [], + "View": { + "Dynamo": { + "ScaleFactor": 1.0, + "HasRunWithoutCrash": true, + "IsVisibleInDynamoLibrary": true, + "Version": "3.6.0.6885", + "RunType": "Automatic", + "RunPeriod": "1000" + }, + "Camera": { + "Name": "_Background Preview", + "EyeX": -17.0, + "EyeY": 24.0, + "EyeZ": 50.0, + "LookX": 12.0, + "LookY": -13.0, + "LookZ": -58.0, + "UpX": 0.0, + "UpY": 1.0, + "UpZ": 0.0 + }, + "ConnectorPins": [], + "NodeViews": [ + { + "Id": "7ce98303309c4466a7556c8a06fb101b", + "Name": "Python Script", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 160.0, + "Y": 273.0 + }, + { + "Id": "afc3a4351a094217b05d451681fd8092", + "Name": "Watch", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 388.0, + "Y": 146.5 + } + ], + "Annotations": [], + "X": 0.0, + "Y": 0.0, + "Zoom": 1.0 + } +} \ No newline at end of file From 22e389774c3423204f343f36632627f4c9724217 Mon Sep 17 00:00:00 2001 From: Ashish Aggarwal Date: Tue, 17 Jun 2025 16:31:32 -0400 Subject: [PATCH 2/3] spelling Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- test/Libraries/DynamoPythonTests/PythonEditTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Libraries/DynamoPythonTests/PythonEditTests.cs b/test/Libraries/DynamoPythonTests/PythonEditTests.cs index ab3d158cabe..68422c9f596 100644 --- a/test/Libraries/DynamoPythonTests/PythonEditTests.cs +++ b/test/Libraries/DynamoPythonTests/PythonEditTests.cs @@ -673,7 +673,7 @@ public void Test_With_Exception_Python() //Verify that the initial run get the expected value Assert.That(watchNode.OutputData.InitialValue, Is.EqualTo("test2")); - //Verity that don't have warnings/errors in the python node + //Verify that don't have warnings/errors in the python node Assert.AreEqual(pythonNode.NodeInfos.Count, 0); var script = pythonNode.Script; From 50247cfe990b61fd54b84a9b1e34fe41da6b7089 Mon Sep 17 00:00:00 2001 From: Ashish Aggarwal Date: Tue, 17 Jun 2025 16:34:03 -0400 Subject: [PATCH 3/3] spelling Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- test/Libraries/DynamoPythonTests/PythonEditTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Libraries/DynamoPythonTests/PythonEditTests.cs b/test/Libraries/DynamoPythonTests/PythonEditTests.cs index 68422c9f596..e359a146413 100644 --- a/test/Libraries/DynamoPythonTests/PythonEditTests.cs +++ b/test/Libraries/DynamoPythonTests/PythonEditTests.cs @@ -677,7 +677,7 @@ public void Test_With_Exception_Python() Assert.AreEqual(pythonNode.NodeInfos.Count, 0); var script = pythonNode.Script; - //This replacing this text in the code will generate an exception in PythonScript node + //Replacing this text in the code will generate an exception in the PythonScript node script = script.Replace("result = \"test2\"", line_update); UpdatePythonNodeContent(pythonNode, script);