diff --git a/src/perf_tests/Python.PerformanceTests.csproj b/src/perf_tests/Python.PerformanceTests.csproj index 2ef942f0d..b437fe532 100644 --- a/src/perf_tests/Python.PerformanceTests.csproj +++ b/src/perf_tests/Python.PerformanceTests.csproj @@ -13,7 +13,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + compile @@ -25,7 +25,7 @@ - + diff --git a/src/runtime/Properties/AssemblyInfo.cs b/src/runtime/Properties/AssemblyInfo.cs index 3b88a6eb5..ffb1308a4 100644 --- a/src/runtime/Properties/AssemblyInfo.cs +++ b/src/runtime/Properties/AssemblyInfo.cs @@ -4,5 +4,5 @@ [assembly: InternalsVisibleTo("Python.EmbeddingTest, PublicKey=00240000048000009400000006020000002400005253413100040000110000005ffd8f49fb44ab0641b3fd8d55e749f716e6dd901032295db641eb98ee46063cbe0d4a1d121ef0bc2af95f8a7438d7a80a3531316e6b75c2dae92fb05a99f03bf7e0c03980e1c3cfb74ba690aca2f3339ef329313bcc5dccced125a4ffdc4531dcef914602cd5878dc5fbb4d4c73ddfbc133f840231343e013762884d6143189")] [assembly: InternalsVisibleTo("Python.Test, PublicKey=00240000048000009400000006020000002400005253413100040000110000005ffd8f49fb44ab0641b3fd8d55e749f716e6dd901032295db641eb98ee46063cbe0d4a1d121ef0bc2af95f8a7438d7a80a3531316e6b75c2dae92fb05a99f03bf7e0c03980e1c3cfb74ba690aca2f3339ef329313bcc5dccced125a4ffdc4531dcef914602cd5878dc5fbb4d4c73ddfbc133f840231343e013762884d6143189")] -[assembly: AssemblyVersion("2.0.38")] -[assembly: AssemblyFileVersion("2.0.38")] +[assembly: AssemblyVersion("2.0.39")] +[assembly: AssemblyFileVersion("2.0.39")] diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index 7c25c9219..c579abaa5 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -5,7 +5,7 @@ Python.Runtime Python.Runtime QuantConnect.pythonnet - 2.0.38 + 2.0.39 false LICENSE https://github.com/pythonnet/pythonnet diff --git a/src/runtime/Types/ClassBase.cs b/src/runtime/Types/ClassBase.cs index d71897605..ded315952 100644 --- a/src/runtime/Types/ClassBase.cs +++ b/src/runtime/Types/ClassBase.cs @@ -94,7 +94,7 @@ public virtual NewReference type_subscript(BorrowedReference idx) public static NewReference tp_richcompare(BorrowedReference ob, BorrowedReference other, int op) { CLRObject co1; - CLRObject? co2; + object co2Inst; BorrowedReference tp = Runtime.PyObject_TYPE(ob); var cls = (ClassBase)GetManagedObject(tp)!; // C# operator methods take precedence over IComparable. @@ -127,17 +127,12 @@ public static NewReference tp_richcompare(BorrowedReference ob, BorrowedReferenc return new NewReference(pytrue); } - co1 = (CLRObject)GetManagedObject(ob)!; - co2 = GetManagedObject(other) as CLRObject; - if (null == co2) + if (!TryGetSecondCompareOperandInstance(ob, other, out co1, out co2Inst)) { return new NewReference(pyfalse); } - object o1 = co1.inst; - object o2 = co2.inst; - - if (Equals(o1, o2)) + if (Equals(co1.inst, co2Inst)) { return new NewReference(pytrue); } @@ -147,12 +142,11 @@ public static NewReference tp_richcompare(BorrowedReference ob, BorrowedReferenc case Runtime.Py_LE: case Runtime.Py_GT: case Runtime.Py_GE: - co1 = (CLRObject)GetManagedObject(ob)!; - co2 = GetManagedObject(other) as CLRObject; - if (co1 == null || co2 == null) + if (!TryGetSecondCompareOperandInstance(ob, other, out co1, out co2Inst)) { return Exceptions.RaiseTypeError("Cannot get managed object"); } + var co1Comp = co1.inst as IComparable; if (co1Comp == null) { @@ -161,7 +155,7 @@ public static NewReference tp_richcompare(BorrowedReference ob, BorrowedReferenc } try { - int cmp = co1Comp.CompareTo(co2.inst); + int cmp = co1Comp.CompareTo(co2Inst); BorrowedReference pyCmp; if (cmp < 0) @@ -208,6 +202,38 @@ public static NewReference tp_richcompare(BorrowedReference ob, BorrowedReferenc } } + private static bool TryGetSecondCompareOperandInstance(BorrowedReference left, BorrowedReference right, out CLRObject co1, out object co2Inst) + { + co2Inst = null; + + co1 = (CLRObject)GetManagedObject(left)!; + if (co1 == null) + { + return false; + } + + var co2 = GetManagedObject(right) as CLRObject; + + // The object comparing against is not a managed object. It could still be a Python object + // that can be compared against (e.g. comparing against a Python string) + if (co2 == null) + { + if (right != null) + { + using var pyCo2 = new PyObject(right); + if (Converter.ToManagedValue(pyCo2, typeof(object), out var result, false)) + { + co2Inst = result; + return true; + } + } + return false; + } + + co2Inst = co2.inst; + return true; + } + /// /// Standard iteration support for instances of reflected types. This /// allows natural iteration over objects that either are IEnumerable