From 80b77a02a5ac28bc23fb7be918e29620d87304e4 Mon Sep 17 00:00:00 2001 From: "Aaron (Qilong)" <173288704@qq.com> Date: Fri, 10 Jul 2020 12:57:28 -0400 Subject: [PATCH 1/5] Regressions (#10877) * Regressions * code cleanup --- .../IronPythonCodeCompletionProviderCore.cs | 3 +-- src/Libraries/DSIronPython/IronPythonEvaluator.cs | 1 - .../DynamoPythonTests/PythonEngineSelectorTests.cs | 12 ------------ 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/Libraries/DSIronPython/IronPythonCodeCompletionProviderCore.cs b/src/Libraries/DSIronPython/IronPythonCodeCompletionProviderCore.cs index f1c9b734bfb..4be71074758 100644 --- a/src/Libraries/DSIronPython/IronPythonCodeCompletionProviderCore.cs +++ b/src/Libraries/DSIronPython/IronPythonCodeCompletionProviderCore.cs @@ -1046,8 +1046,7 @@ public void Initialize(string dynamoCorePath) } // If IronPython.Std folder is excluded from DynamoCore (which could be user mistake or integrator exclusion) - // Or if the execution path is different than Dynamo root folder - if (!Directory.Exists(pythonLibDir) || pythonLibDir != executionPath) + if (!Directory.Exists(pythonLibDir)) { // Try to load IronPython from extension package pythonLibDir = Path.Combine((new DirectoryInfo(Path.GetDirectoryName(executionPath))).Parent.FullName, IronPythonEvaluator.packageExtraFolderName, IronPythonEvaluator.PythonLibName); diff --git a/src/Libraries/DSIronPython/IronPythonEvaluator.cs b/src/Libraries/DSIronPython/IronPythonEvaluator.cs index 0ceae74b9cb..94077a020dc 100644 --- a/src/Libraries/DSIronPython/IronPythonEvaluator.cs +++ b/src/Libraries/DSIronPython/IronPythonEvaluator.cs @@ -64,7 +64,6 @@ private static string PythonStandardLibPath() pythonLibDir = Path.Combine(Path.GetDirectoryName(executionPath), PythonLibName); // If IronPython.Std folder is excluded from DynamoCore (which could be user mistake or integrator exclusion) - // Or if the execution path is different than Dynamo root folder if (!Directory.Exists(pythonLibDir)) { // Try to load IronPython from extension package diff --git a/test/Libraries/DynamoPythonTests/PythonEngineSelectorTests.cs b/test/Libraries/DynamoPythonTests/PythonEngineSelectorTests.cs index ada0ba9e5aa..e2a0dc2c96e 100644 --- a/test/Libraries/DynamoPythonTests/PythonEngineSelectorTests.cs +++ b/test/Libraries/DynamoPythonTests/PythonEngineSelectorTests.cs @@ -16,24 +16,12 @@ protected override void GetLibrariesToPreload(List libraries) base.GetLibrariesToPreload(libraries); } - /// - /// This test will cover the initial state of the Singleton - /// - [Test] - public void TestEngineSelectorInitial_State() - { - Assert.AreEqual(false, PythonEngineSelector.lazy.IsValueCreated); - Assert.AreEqual(false, PythonEngineSelector.IsCPythonEnabled); - Assert.AreEqual(false, PythonEngineSelector.IsIronPythonEnabled); - } - /// /// This test will cover the use case of the API to query certain Python engine ability for evaluation /// [Test] public void TestEngineSelectorInitialization() { - Assert.AreEqual(false, PythonEngineSelector.lazy.IsValueCreated); PythonEngineSelector.Instance.GetEvaluatorInfo(PythonEngineVersion.IronPython2, out string evaluatorClass, out string evaluationMethod); Assert.AreEqual(true, PythonEngineSelector.lazy.IsValueCreated); Assert.AreEqual(evaluatorClass, PythonEngineSelector.IronPythonEvaluatorClass); From b7c48507e4342a78577aad8fe90b6953da454065 Mon Sep 17 00:00:00 2001 From: Astul-Betizagasti <66637541+Astul-Betizagasti@users.noreply.github.com> Date: Fri, 10 Jul 2020 14:26:12 -0300 Subject: [PATCH 2/5] [DYN-2894] Annotation fix (#10876) * UpdateBoundaryFromSelection Fix * Fix * Comment spelling correction * Performance changes * Revert note hight changes * Revert "Revert note hight changes" This reverts commit aceaffa03b63ef36c3a0227e6b8854f526dc60f8. * Removal of note check Co-authored-by: Astul B --- .../Graph/Annotations/AnnotationModel.cs | 57 ++----------------- 1 file changed, 6 insertions(+), 51 deletions(-) diff --git a/src/DynamoCore/Graph/Annotations/AnnotationModel.cs b/src/DynamoCore/Graph/Annotations/AnnotationModel.cs index b42312d5c7c..1febdd9cb29 100644 --- a/src/DynamoCore/Graph/Annotations/AnnotationModel.cs +++ b/src/DynamoCore/Graph/Annotations/AnnotationModel.cs @@ -290,58 +290,26 @@ internal void UpdateBoundaryFromSelection() var regionY = groupModels.Min(y => y.Y) - ExtendSize - (TextBlockHeight == 0.0 ? MinTextHeight : TextBlockHeight); //calculates the distance between the nodes - var xDistance = groupModels.Max(x => x.X) - regionX; - var yDistance = groupModels.Max(x => x.Y) - regionY; - - var widthandheight = CalculateWidthAndHeight(); - - var maxWidth = widthandheight.Item1; - var maxHeight = widthandheight.Item2; + var xDistance = groupModels.Max(x => (x.X + x.Width)) - regionX; + var yDistance = groupModels.Max(x => (x.Y + x.Height)) - regionY; // InitialTop is to store the Y value without the Textblock height this.InitialTop = groupModels.Min(y => y.Y); + var region = new Rect2D { X = regionX, Y = regionY, - Width = xDistance + maxWidth + ExtendSize, - Height = yDistance + maxHeight + ExtendSize + Width = xDistance + ExtendSize, + Height = yDistance + ExtendSize + ExtendYHeight }; - + this.X = region.X; this.Y = region.Y; this.Width = Math.Max(region.Width, TextMaxWidth + ExtendSize); this.Height = region.Height; - //Calculate the boundary if there is any overlap - ModelBase overlap = null; - foreach (var nodesList in Nodes) - { - if (!region.Contains(nodesList.Rect)) - { - overlap = nodesList; - if (overlap.Rect.Top < this.X || - overlap.Rect.Bottom > region.Bottom) //Overlap in height - increase the region height - { - if (overlap.Rect.Bottom - region.Bottom > 0) - { - this.Height += overlap.Rect.Bottom - region.Bottom + ExtendSize + ExtendYHeight; - } - region.Height = this.Height; - } - if (overlap.Rect.Left < this.Y || - overlap.Rect.Right > region.Right) //Overlap in width - increase the region width - { - if (overlap.Rect.Right - region.Right > 0) - { - this.Width += overlap.Rect.Right - region.Right + ExtendSize; - } - region.Width = this.Width; - } - } - } - //Initial Height is to store the Actual height of the group. //that is the height should be the initial height without the textblock height. if (this.InitialHeight <= 0.0) @@ -358,20 +326,7 @@ internal void UpdateBoundaryFromSelection() /// Group the Models based on Height and Width /// /// the width and height of the last model - private Tuple CalculateWidthAndHeight() - { - var xgroup = Nodes.OrderBy(x => x.X).ToList(); - var ygroup = Nodes.OrderBy(x => x.Y).ToList(); - double yheight = ygroup.Last().Height; - - //If the last model is Node, then increase the height so that - //node border does not overlap with the group - if (ygroup.Last() is NodeModel) - yheight = yheight + ExtendYHeight; - return Tuple.Create(xgroup.Last().Width, yheight); - } - #region Serialization/Deserialization Methods protected override bool UpdateValueCore(UpdateValueParams updateValueParams) From 329d9caa9988783e54e38e28233c726b93ec16fb Mon Sep 17 00:00:00 2001 From: Astul-Betizagasti <66637541+Astul-Betizagasti@users.noreply.github.com> Date: Fri, 10 Jul 2020 14:27:08 -0300 Subject: [PATCH 3/5] [DYN-2870] Graph Workspaces Coverage (#10873) * Removal of unused code * Revert "Removal of unused code" This reverts commit c78dfe9afbdd95d1d326c0d36bac7c65a69f25b8. * Added Obsolete Tag * Message change * Tests1 * Tests changes --- test/DynamoCoreTests/DynamoCoreTests.csproj | 2 + .../CustomNodeWorkspaceModelTests.cs | 60 +++++++++++++++++++ .../Workspaces/HomeWorkspaceModelTests.cs | 58 ++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 test/DynamoCoreTests/Graph/Workspaces/CustomNodeWorkspaceModelTests.cs create mode 100644 test/DynamoCoreTests/Graph/Workspaces/HomeWorkspaceModelTests.cs diff --git a/test/DynamoCoreTests/DynamoCoreTests.csproj b/test/DynamoCoreTests/DynamoCoreTests.csproj index 89e4a928bfd..eb0f24097c7 100644 --- a/test/DynamoCoreTests/DynamoCoreTests.csproj +++ b/test/DynamoCoreTests/DynamoCoreTests.csproj @@ -96,6 +96,8 @@ + + diff --git a/test/DynamoCoreTests/Graph/Workspaces/CustomNodeWorkspaceModelTests.cs b/test/DynamoCoreTests/Graph/Workspaces/CustomNodeWorkspaceModelTests.cs new file mode 100644 index 00000000000..4ba8349b3a1 --- /dev/null +++ b/test/DynamoCoreTests/Graph/Workspaces/CustomNodeWorkspaceModelTests.cs @@ -0,0 +1,60 @@ +using System.IO; +using System.Linq; +using Dynamo.Graph.Workspaces; +using NUnit.Framework; + +namespace Dynamo.Tests +{ + /// + /// Class containing tests for the CustomNodeWorkspaceModel class + /// + [TestFixture] + class CustomNodeWorkspaceModelTests : DynamoModelTestBase + { + public void OpenTestFile(string folder, string fileName) + { + var examplePath = Path.Combine(TestDirectory, folder, fileName); + OpenModel(examplePath); + } + + [Test] + [Category("UnitTests")] + public void OnPropertyNameChangedTest() + { + OpenTestFile(@"core\CustomNodes", "add_Read_only.dyf"); + var nodeWorkspace = CurrentDynamoModel.Workspaces.FirstOrDefault(x => x is CustomNodeWorkspaceModel); + Assert.IsNotNull(nodeWorkspace); + + OpenTestFile(@"core\CustomNodes", "TestAdd.dyn"); + var homeWorkspace = CurrentDynamoModel.CurrentWorkspace as HomeWorkspaceModel; + Assert.NotNull(homeWorkspace); + + //Changes the Name property so that the event is raised + nodeWorkspace.Name = "NewNodeName"; + + var resultNode = homeWorkspace.Nodes.FirstOrDefault(x => x.Name == "NewNodeName"); + Assert.IsNotNull(resultNode); + } + + [Test] + [Category("UnitTests")] + public void GetSharedNameTest() + { + var fileName = "add_Read_only"; + OpenTestFile(@"core\CustomNodes", fileName+".dyf"); + var nodeWorkspace = CurrentDynamoModel.Workspaces.FirstOrDefault(x => x is CustomNodeWorkspaceModel); + Assert.IsNotNull(nodeWorkspace); + + var result = nodeWorkspace.GetSharedName(); + Assert.AreEqual(fileName,result); + + //Set fileName to null to simulate it is not a saved file + nodeWorkspace.FileName = null; + var expected = nodeWorkspace.Name; + + result = nodeWorkspace.GetSharedName(); + + Assert.AreEqual(expected,result); + } + } +} diff --git a/test/DynamoCoreTests/Graph/Workspaces/HomeWorkspaceModelTests.cs b/test/DynamoCoreTests/Graph/Workspaces/HomeWorkspaceModelTests.cs new file mode 100644 index 00000000000..2e6185176c0 --- /dev/null +++ b/test/DynamoCoreTests/Graph/Workspaces/HomeWorkspaceModelTests.cs @@ -0,0 +1,58 @@ +using System.IO; +using Dynamo.Graph.Workspaces; +using Dynamo.Models; +using NUnit.Framework; + +namespace Dynamo.Tests +{ + /// + /// Class containing tests for the HomeWorkspaceModel class + /// + [TestFixture] + class HomeWorkspaceModelTests : DynamoModelTestBase + { + private bool eventWasRaised; + private string objectFileName; + + public void OpenTestFile(string folder, string fileName) + { + var examplePath = Path.Combine(TestDirectory, folder, fileName); + OpenModel(examplePath); + } + + [SetUp] + public void Init() + { + eventWasRaised = false; + objectFileName = ""; + } + + [Test] + [Category("UnitTests")] + public void OnPreviewGraphCompletedTest() + { + //Loads a file with a valid graph on the Home workspace + OpenTestFile(@"core\number", "TestBigNumber.dyn"); + var homeWorkspace = CurrentDynamoModel.CurrentWorkspace as HomeWorkspaceModel; + Assert.NotNull(homeWorkspace); + + //Gets results from raised event + homeWorkspace.SetNodeDeltaState += EventHandler; + + homeWorkspace.Run(); + homeWorkspace.GetExecutingNodes(true); + + homeWorkspace.SetNodeDeltaState -= EventHandler; + + Assert.IsTrue(eventWasRaised); + Assert.AreEqual(homeWorkspace.FileName, objectFileName); + } + + private void EventHandler (object workspace, DeltaComputeStateEventArgs d) + { + eventWasRaised = true; + var eventParamWorkspace = workspace as HomeWorkspaceModel; + objectFileName = eventParamWorkspace.FileName; + } + } +} From b33821c48c4e008c52f6fc99f71c6fc5024c4827 Mon Sep 17 00:00:00 2001 From: Bruno Yorda <34453173+byorda-glb@users.noreply.github.com> Date: Fri, 10 Jul 2020 13:05:32 -0500 Subject: [PATCH 4/5] Increase code coverage in the Graph folder (#10874) * Added tests for NodeModel * Added tests for NodeModel * Revert "Added tests for NodeModel" This reverts commit 4434d5fcbd1f452ac17d9555d73c6a185a37d5c8. * Update NodeModelTests.cs * Removed a test and marked the properties as obsolete * Changed Obsolete for IsObsolete applying it only to the setter * Updated message * Added tests for NodeModel * Deprecated PrintExpression and removed the associated test. * DYN-2561 - Coverage Connectors folder I added the ConnectorModelConnectTest() method to increase the coverage in the ConnectorModel class. The internal class InvalidPortException was deleted due that is no used (no reference was found in all the Dynamo solution). I got approval from Aaron and Michael in the Autodesk Slack Channel. For the DeserializeCore(XmlElement nodeElement, SaveContext context) I deleted the commented code. I got approval from Aaron and Michael in the Autodesk Slack Channel. * Added tests for Attributes * Replaced a string with its associated resource. Co-authored-by: Roberto Tellez --- test/DynamoCoreTests/DynamoCoreTests.csproj | 1 + .../Graph/Nodes/NodeAttributesTests.cs | 151 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 test/DynamoCoreTests/Graph/Nodes/NodeAttributesTests.cs diff --git a/test/DynamoCoreTests/DynamoCoreTests.csproj b/test/DynamoCoreTests/DynamoCoreTests.csproj index eb0f24097c7..60503bcf2c7 100644 --- a/test/DynamoCoreTests/DynamoCoreTests.csproj +++ b/test/DynamoCoreTests/DynamoCoreTests.csproj @@ -95,6 +95,7 @@ + diff --git a/test/DynamoCoreTests/Graph/Nodes/NodeAttributesTests.cs b/test/DynamoCoreTests/Graph/Nodes/NodeAttributesTests.cs new file mode 100644 index 00000000000..f3ac7096e3f --- /dev/null +++ b/test/DynamoCoreTests/Graph/Nodes/NodeAttributesTests.cs @@ -0,0 +1,151 @@ +using System; +using System.Linq; +using CoreNodeModels.Properties; +using Dynamo.Graph.Nodes; +using NUnit.Framework; + +namespace Dynamo.Tests +{ + /// + /// This file contains tests for the classes in the Attributes file. + /// + [TestFixture] + class NodeAttributesTests + { + [Test] + [Category("UnitTests")] + public void NodeSearchTagsAttributeConstructorTest() + { + //resourceType is null + string tagsID = "tagsID"; + Type resourceType = null; + + Assert.Throws(() => _ = new NodeSearchTagsAttribute(tagsID, resourceType)); + } + + [Test] + [Category("UnitTests")] + public void NodeDescriptionAttributeConstructorTest() + { + //resourceType is null + Assert.Throws(() => _ = new NodeDescriptionAttribute("", null)); + + //resourceType is valid + string descriptionResourceID = "WatchNodeDescription"; + Type resourceType = typeof(Resources); + + var attr = new NodeDescriptionAttribute(descriptionResourceID, resourceType); + Assert.AreEqual(Resources.WatchNodeDescription, attr.ElementDescription); + + //resourceType is valid but descriptionResourceID is not + descriptionResourceID = "Nil"; + resourceType = typeof(Resources); + + attr = new NodeDescriptionAttribute(descriptionResourceID, resourceType); + Assert.AreEqual(descriptionResourceID, attr.ElementDescription); + } + + [Test] + [Category("UnitTests")] + public void DoNotLoadOnPlatformsAttributeConstructorTest() + { + //values is null + var attr = new DoNotLoadOnPlatformsAttribute(null); + Assert.AreEqual(null, attr.Values); + + //values is valid + attr = new DoNotLoadOnPlatformsAttribute(new string[] { "" }); + Assert.AreEqual(1, attr.Values.Length); + } + + [Test] + [Category("UnitTests")] + public void NodeObsoleteAttributeConstructorTest() + { + //base with message + var attr = new NodeObsoleteAttribute("Message"); + Assert.AreEqual("Message", attr.Message); + + //resourceType is null + Assert.Throws(() => _ = new NodeObsoleteAttribute("", null)); + + //resourceType is valid + string descriptionResourceID = "WatchNodeDescription"; + Type resourceType = typeof(Resources); + + attr = new NodeObsoleteAttribute(descriptionResourceID, resourceType); + Assert.AreEqual(Resources.WatchNodeDescription, attr.Message); + + //resourceType is valid but descriptionResourceID is not + descriptionResourceID = "Nil"; + resourceType = typeof(Resources); + + attr = new NodeObsoleteAttribute(descriptionResourceID, resourceType); + Assert.AreEqual(descriptionResourceID, attr.Message); + } + + [Test] + [Category("UnitTests")] + public void InPortNamesAttributeConstructorTest() + { + //resourceType is null + var attr = new InPortNamesAttribute(null, new string[] { "" }); + Assert.AreEqual(0, attr.PortNames.Count()); + + //resourceType is valid + string[] resourceNames = { "WatchNodeDescription" }; + Type resourceType = typeof(Resources); + + attr = new InPortNamesAttribute(resourceType, resourceNames); + Assert.AreEqual(1, attr.PortNames.Count()); + } + + [Test] + [Category("UnitTests")] + public void InPortTypesAttributeConstructorTest() + { + //resourceType is null + var attr = new InPortTypesAttribute(null, new string[] { "" }); + Assert.AreEqual(0, attr.PortTypes.Count()); + + //resourceType is valid + string[] resourceNames = { "WatchNodeDescription" }; + Type resourceType = typeof(Resources); + + attr = new InPortTypesAttribute(resourceType, resourceNames); + Assert.AreEqual(1, attr.PortTypes.Count()); + } + + [Test] + [Category("UnitTests")] + public void OutPortNamesAttributeConstructorTest() + { + //resourceType is null + var attr = new OutPortNamesAttribute(null, new string[] { "" }); + Assert.AreEqual(0, attr.PortNames.Count()); + + //resourceType is valid + string[] resourceNames = { "WatchNodeDescription" }; + Type resourceType = typeof(Resources); + + attr = new OutPortNamesAttribute(resourceType, resourceNames); + Assert.AreEqual(1, attr.PortNames.Count()); + } + + [Test] + [Category("UnitTests")] + public void OutPortTypesAttributeConstructorTest() + { + //resourceType is null + var attr = new OutPortTypesAttribute(null, new string[] { "" }); + Assert.AreEqual(0, attr.PortTypes.Count()); + + //resourceType is valid + string[] resourceNames = { "WatchNodeDescription" }; + Type resourceType = typeof(Resources); + + attr = new OutPortTypesAttribute(resourceType, resourceNames); + Assert.AreEqual(1, attr.PortTypes.Count()); + } + } +} \ No newline at end of file From 11f953bcd20f4a26119aabf07c49fc7d4304edb2 Mon Sep 17 00:00:00 2001 From: Martin Misol Monzo Date: Fri, 10 Jul 2020 14:58:24 -0400 Subject: [PATCH 5/5] Convert Python iterable to IList and IEnumerable (#10879) Adds support to convert any Python iterable to an IList or IEnumerable in the context of a function call using the CPython engine. The decoder now checks if the PyObject returned is iterable instead of a sequence, which is supported by the function we are using in Python.NET. Also, IEnumerable, both generic and non-generic, is declared as a target type to allow more conversion scenarios. This should now allow converting dictionary view types, set and frozenset to IList. It should also allow these and any other types that are iterable (list, tuple, dictionary) to be converted to IEnumerable. --- .../DSCPython/Encoders/ListEncodeDecoder.cs | 5 +- test/Engine/FFITarget/DummyCollection.cs | 5 + .../PythonEvalTestsWithLibraries.cs | 100 ++++++++++++++++-- 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/src/Libraries/DSCPython/Encoders/ListEncodeDecoder.cs b/src/Libraries/DSCPython/Encoders/ListEncodeDecoder.cs index fd0601491a5..9572837615e 100644 --- a/src/Libraries/DSCPython/Encoders/ListEncodeDecoder.cs +++ b/src/Libraries/DSCPython/Encoders/ListEncodeDecoder.cs @@ -11,7 +11,8 @@ internal class ListEncoderDecoder : IPyObjectEncoder, IPyObjectDecoder private static readonly Type[] decodableTypes = new Type[] { typeof(IList), typeof(ArrayList), - typeof(IList<>), typeof(List<>) + typeof(IList<>), typeof(List<>), + typeof(IEnumerable), typeof(IEnumerable<>) }; public bool CanDecode(PyObject objectType, Type targetType) @@ -30,7 +31,7 @@ public bool CanEncode(Type type) public bool TryDecode(PyObject pyObj, out T value) { - if (!PySequence.IsSequenceType(pyObj)) + if (!PyIter.IsIterable(pyObj)) { value = default; return false; diff --git a/test/Engine/FFITarget/DummyCollection.cs b/test/Engine/FFITarget/DummyCollection.cs index 73f34f82362..47e79b0cdc8 100644 --- a/test/Engine/FFITarget/DummyCollection.cs +++ b/test/Engine/FFITarget/DummyCollection.cs @@ -12,6 +12,11 @@ public static IList ReturnIList(IEnumerable data) return data.ToList(); } + public static IEnumerable ReturnIEnumerable(IEnumerable data) + { + return data; + } + public static IEnumerable ReturnIEnumerableOfInt(IEnumerable data) { return data; diff --git a/test/Libraries/DynamoPythonTests/PythonEvalTestsWithLibraries.cs b/test/Libraries/DynamoPythonTests/PythonEvalTestsWithLibraries.cs index b4c1825582d..9ea2da3e077 100644 --- a/test/Libraries/DynamoPythonTests/PythonEvalTestsWithLibraries.cs +++ b/test/Libraries/DynamoPythonTests/PythonEvalTestsWithLibraries.cs @@ -52,6 +52,8 @@ public void TestListDecoding() import sys import clr clr.AddReference('DSCoreNodes') +clr.AddReference('FFITarget') +from FFITarget import DummyCollection from DSCore import List l = ['a'] @@ -66,7 +68,7 @@ from DSCore import List l3 = [[1,2],[3,4]] # Python list (nested) => .NET IList> -flatennedList = List.Flatten(l3) +flattenedList = List.Flatten(l3) l4 = [] # Python list (empty) => .NET IList @@ -74,13 +76,21 @@ from DSCore import List sum = 0 # Python-wrapped .NET List can be iterated over -for i in flatennedList: +for i in flattenedList: sum = sum + i -OUT = untypedList, typedList, flatennedList, elementCount, sum +l5 = [1,2,3,4] +# Python list => .NET IEnumerable<> +max = List.MaximumItem(l5) + +# Python list => .NET IEnumerable +enumerable = DummyCollection.ReturnIEnumerable(l2) + +OUT = untypedList, typedList, flattenedList, elementCount, sum, max, enumerable "; var empty = new ArrayList(); - var expected = new ArrayList { new ArrayList { "a", "b", "c" }, new ArrayList { "b", "b" }, new ArrayList { 1, 2, 3, 4 }, 0, 10 }; + var expected = new ArrayList { new ArrayList { "a", "b", "c" }, new ArrayList { "b", "b" }, new ArrayList { 1, 2, 3, 4 }, 0, 10, 4 + , new ArrayList { "a", "b" } }; foreach (var pythonEvaluator in Evaluators) { var result = pythonEvaluator(code, empty, empty); @@ -182,8 +192,8 @@ public void TestDictionaryDecodingCPython() import sys import clr clr.AddReference('FFITarget') -clr.AddReference('DesignScriptBuiltin') -from DesignScript.Builtin import Dictionary +clr.AddReference('DSCoreNodes') +from DSCore import List from FFITarget import DummyCollection d = {'one': 1, 'two': 2, 'three': 3} @@ -196,17 +206,87 @@ from FFITarget import DummyCollection typedDictionary = DummyCollection.AcceptDictionary(d) typedDictionary['four'] = 4 -OUT = untypedDictionary, typedDictionary +# Python dict => .NET IEnumerable - Returns keys in both engines +sortedKeys = List.Sort(d) + +OUT = untypedDictionary, typedDictionary, sortedKeys "; var empty = new ArrayList(); - var expected = new Dictionary { + var expectedDictionary = new Dictionary { { "one", 1 }, { "two", 2 }, { "three", 3 }, { "four", 4 } }; + var expectedKeys = new List { "one", "three", "two" }; var result = DSCPython.CPythonEvaluator.EvaluatePythonScript(code, empty, empty); Assert.IsTrue(result is IList); - foreach (var dict in result as IList) + var resultList = result as IList; + for (int i = 0; i < 2; i++) + { + Assert.IsTrue(resultList[i] is IDictionary); + DictionaryAssert(expectedDictionary, resultList[i] as IDictionary); + } + Assert.IsTrue(resultList[2] is IList); + CollectionAssert.AreEqual(expectedKeys, resultList[2] as IList); + } + + [Test] + public void TestDictionaryViewsDecoding() + { + var code = @" +import clr +clr.AddReference('DSCoreNodes') +from DSCore import List + +d = {'one': 1, 'two': 2, 'three': 3} + +dk = List.AddItemToEnd('four', d.keys()) +dv = List.AddItemToEnd(4, d.values()) +di = List.AddItemToEnd(('four', 4), d.items()) + +OUT = dk, dv, di +"; + var empty = new ArrayList(); + var expected = new ArrayList[] { + new ArrayList { "one", "two", "three", "four" }, + new ArrayList { 1, 2, 3, 4 }, + new ArrayList { new ArrayList { "one", 1 }, new ArrayList { "two", 2 }, new ArrayList { "three", 3 }, new ArrayList { "four", 4 } } + }; + foreach (var pythonEvaluator in Evaluators) + { + var result = pythonEvaluator(code, empty, empty); + Assert.IsTrue(result is IEnumerable); + var i = 0; + foreach (var item in result as IEnumerable) + { + Assert.IsTrue(item is IEnumerable); + CollectionAssert.AreEquivalent(expected[i], item as IEnumerable); + i++; + } + } + } + + [Test] + public void TestSetDecodingCPython() + { + var code = @" +import clr +clr.AddReference('DSCoreNodes') +from DSCore import List + +s = { 'hello' } +fs = frozenset(s) +# Python set => .NET IList - Does not work in IronPython +s2 = List.AddItemToEnd('world', s) +fs2 = List.AddItemToEnd('world', fs) +OUT = s2, fs2 +"; + var empty = new ArrayList(); + var expected = new string[] { "hello", "world" }; + var result = DSCPython.CPythonEvaluator.EvaluatePythonScript(code, empty, empty); + Assert.IsTrue(result is IEnumerable); + foreach (var item in result as IEnumerable) { - DictionaryAssert(expected, dict as IDictionary); + Assert.IsTrue(item is IEnumerable); + CollectionAssert.AreEquivalent(expected, item as IEnumerable); } }