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