diff --git a/src/embed_tests/TestConverter.cs b/src/embed_tests/TestConverter.cs index e586eda1b..c5ed1d3af 100644 --- a/src/embed_tests/TestConverter.cs +++ b/src/embed_tests/TestConverter.cs @@ -132,6 +132,26 @@ public void ToNullable() Assert.AreEqual(Const, ni); } + [Test] + public void DerivedFloatIsNotFloat() + { + using var scope = Py.CreateScope(); + scope.Exec(@"class DerivedFloat(float): pass"); + using var derivedFloat = scope.Eval("DerivedFloat(42.0)"); + object dotnetValue = derivedFloat.As(); + Assert.IsInstanceOf(dotnetValue); + } + + [Test] + public void DerivedIntIsNotInt() + { + using var scope = Py.CreateScope(); + scope.Exec(@"class DerivedInt(int): pass"); + using var derivedInt = scope.Eval("DerivedInt(42)"); + object dotnetValue = derivedInt.As(); + Assert.IsInstanceOf(dotnetValue); + } + [Test] public void BigIntExplicit() { diff --git a/src/runtime/Converter.cs b/src/runtime/Converter.cs index 3c46e9034..b0547637b 100644 --- a/src/runtime/Converter.cs +++ b/src/runtime/Converter.cs @@ -361,17 +361,17 @@ internal static bool ToManagedValue(BorrowedReference value, Type obType, // conversions (Python string -> managed string). if (obType == objectType) { - if (Runtime.PyString_Check(value)) + if (Runtime.PyString_CheckExact(value)) { return ToPrimitive(value, stringType, out result, setError); } - if (Runtime.PyBool_Check(value)) + if (Runtime.PyBool_CheckExact(value)) { return ToPrimitive(value, boolType, out result, setError); } - if (Runtime.PyFloat_Check(value)) + if (Runtime.PyFloat_CheckExact(value)) { return ToPrimitive(value, doubleType, out result, setError); } diff --git a/src/runtime/Runtime.cs b/src/runtime/Runtime.cs index 6238119ff..7110f3cb0 100644 --- a/src/runtime/Runtime.cs +++ b/src/runtime/Runtime.cs @@ -1094,8 +1094,13 @@ internal static nint PyBuffer_SizeFromFormat(string format) internal static bool PyInt_Check(BorrowedReference ob) => PyObject_TypeCheck(ob, PyLongType); + internal static bool PyInt_CheckExact(BorrowedReference ob) + => PyObject_TypeCheckExact(ob, PyLongType); + internal static bool PyBool_Check(BorrowedReference ob) => PyObject_TypeCheck(ob, PyBoolType); + internal static bool PyBool_CheckExact(BorrowedReference ob) + => PyObject_TypeCheckExact(ob, PyBoolType); internal static NewReference PyInt_FromInt32(int value) => PyLong_FromLongLong(value); @@ -1141,6 +1146,8 @@ internal static NewReference PyLong_FromString(string value, int radix) internal static bool PyFloat_Check(BorrowedReference ob) => PyObject_TypeCheck(ob, PyFloatType); + internal static bool PyFloat_CheckExact(BorrowedReference ob) + => PyObject_TypeCheckExact(ob, PyFloatType); /// /// Return value: New reference. @@ -1282,9 +1289,9 @@ internal static bool PyFloat_Check(BorrowedReference ob) // Python string API //==================================================================== internal static bool PyString_Check(BorrowedReference ob) - { - return PyObject_TYPE(ob) == PyStringType; - } + => PyObject_TypeCheck(ob, PyStringType); + internal static bool PyString_CheckExact(BorrowedReference ob) + => PyObject_TypeCheckExact(ob, PyStringType); internal static NewReference PyString_FromString(string value) { @@ -1643,6 +1650,8 @@ internal static bool PyType_IsSubtype(BorrowedReference t1, BorrowedReference t2 return Delegates.PyType_IsSubtype(t1, t2); } + internal static bool PyObject_TypeCheckExact(BorrowedReference ob, BorrowedReference tp) + => PyObject_TYPE(ob) == tp; internal static bool PyObject_TypeCheck(BorrowedReference ob, BorrowedReference tp) { BorrowedReference t = PyObject_TYPE(ob);