Skip to content

Commit 02b6c2f

Browse files
authored
Merge pull request #1986 from losttech/FloatDerivedCodec
Allow decoders to decode Python types derived from primitives
2 parents ce76dae + 782a0e5 commit 02b6c2f

File tree

3 files changed

+45
-7
lines changed

3 files changed

+45
-7
lines changed

src/embed_tests/Codecs.cs

+13
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,19 @@ from datetime import datetime
355355
scope.Exec("Codecs.AcceptsDateTime(datetime(2021, 1, 22))");
356356
}
357357

358+
[Test]
359+
public void FloatDerivedDecoded()
360+
{
361+
using var scope = Py.CreateScope();
362+
scope.Exec(@"class FloatDerived(float): pass");
363+
using var floatDerived = scope.Eval("FloatDerived");
364+
var decoder = new DecoderReturningPredefinedValue<object>(floatDerived, 42);
365+
PyObjectConversions.RegisterDecoder(decoder);
366+
using var result = scope.Eval("FloatDerived()");
367+
object decoded = result.As<object>();
368+
Assert.AreEqual(42, decoded);
369+
}
370+
358371
[Test]
359372
public void ExceptionDecodedNoInstance()
360373
{

src/runtime/Converter.cs

+20-4
Original file line numberDiff line numberDiff line change
@@ -361,28 +361,44 @@ internal static bool ToManagedValue(BorrowedReference value, Type obType,
361361
// conversions (Python string -> managed string).
362362
if (obType == objectType)
363363
{
364-
if (Runtime.PyString_Check(value))
364+
if (Runtime.PyString_CheckExact(value))
365365
{
366366
return ToPrimitive(value, stringType, out result, setError);
367367
}
368368

369-
if (Runtime.PyBool_Check(value))
369+
if (Runtime.PyBool_CheckExact(value))
370370
{
371371
return ToPrimitive(value, boolType, out result, setError);
372372
}
373373

374-
if (Runtime.PyFloat_Check(value))
374+
if (Runtime.PyFloat_CheckExact(value))
375375
{
376376
return ToPrimitive(value, doubleType, out result, setError);
377377
}
378378

379-
// give custom codecs a chance to take over conversion of ints and sequences
379+
// give custom codecs a chance to take over conversion
380+
// of ints, sequences, and types derived from primitives
380381
BorrowedReference pyType = Runtime.PyObject_TYPE(value);
381382
if (PyObjectConversions.TryDecode(value, pyType, obType, out result))
382383
{
383384
return true;
384385
}
385386

387+
if (Runtime.PyString_Check(value))
388+
{
389+
return ToPrimitive(value, stringType, out result, setError);
390+
}
391+
392+
if (Runtime.PyBool_Check(value))
393+
{
394+
return ToPrimitive(value, boolType, out result, setError);
395+
}
396+
397+
if (Runtime.PyFloat_Check(value))
398+
{
399+
return ToPrimitive(value, doubleType, out result, setError);
400+
}
401+
386402
if (Runtime.PyInt_Check(value))
387403
{
388404
result = new PyInt(value);

src/runtime/Runtime.cs

+12-3
Original file line numberDiff line numberDiff line change
@@ -1094,8 +1094,13 @@ internal static nint PyBuffer_SizeFromFormat(string format)
10941094
internal static bool PyInt_Check(BorrowedReference ob)
10951095
=> PyObject_TypeCheck(ob, PyLongType);
10961096

1097+
internal static bool PyInt_CheckExact(BorrowedReference ob)
1098+
=> PyObject_TypeCheckExact(ob, PyLongType);
1099+
10971100
internal static bool PyBool_Check(BorrowedReference ob)
10981101
=> PyObject_TypeCheck(ob, PyBoolType);
1102+
internal static bool PyBool_CheckExact(BorrowedReference ob)
1103+
=> PyObject_TypeCheckExact(ob, PyBoolType);
10991104

11001105
internal static NewReference PyInt_FromInt32(int value) => PyLong_FromLongLong(value);
11011106

@@ -1141,6 +1146,8 @@ internal static NewReference PyLong_FromString(string value, int radix)
11411146

11421147
internal static bool PyFloat_Check(BorrowedReference ob)
11431148
=> PyObject_TypeCheck(ob, PyFloatType);
1149+
internal static bool PyFloat_CheckExact(BorrowedReference ob)
1150+
=> PyObject_TypeCheckExact(ob, PyFloatType);
11441151

11451152
/// <summary>
11461153
/// Return value: New reference.
@@ -1282,9 +1289,9 @@ internal static bool PyFloat_Check(BorrowedReference ob)
12821289
// Python string API
12831290
//====================================================================
12841291
internal static bool PyString_Check(BorrowedReference ob)
1285-
{
1286-
return PyObject_TYPE(ob) == PyStringType;
1287-
}
1292+
=> PyObject_TypeCheck(ob, PyStringType);
1293+
internal static bool PyString_CheckExact(BorrowedReference ob)
1294+
=> PyObject_TypeCheckExact(ob, PyStringType);
12881295

12891296
internal static NewReference PyString_FromString(string value)
12901297
{
@@ -1643,6 +1650,8 @@ internal static bool PyType_IsSubtype(BorrowedReference t1, BorrowedReference t2
16431650
return Delegates.PyType_IsSubtype(t1, t2);
16441651
}
16451652

1653+
internal static bool PyObject_TypeCheckExact(BorrowedReference ob, BorrowedReference tp)
1654+
=> PyObject_TYPE(ob) == tp;
16461655
internal static bool PyObject_TypeCheck(BorrowedReference ob, BorrowedReference tp)
16471656
{
16481657
BorrowedReference t = PyObject_TYPE(ob);

0 commit comments

Comments
 (0)