Skip to content

Commit 9a0ceb6

Browse files
committed
Implement IConvertible interface on PyObject
1 parent 86c6a7f commit 9a0ceb6

File tree

6 files changed

+67
-1
lines changed

6 files changed

+67
-1
lines changed

src/runtime/Converter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ internal static int ToInt32(BorrowedReference value)
550550
/// <summary>
551551
/// Convert a Python value to an instance of a primitive managed type.
552552
/// </summary>
553-
private static bool ToPrimitive(BorrowedReference value, Type obType, out object? result, bool setError)
553+
internal static bool ToPrimitive(BorrowedReference value, Type obType, out object? result, bool setError)
554554
{
555555
result = null;
556556
if (obType.IsEnum)

src/runtime/PythonTypes/PyFloat.cs

+2
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,7 @@ public static PyFloat AsFloat(PyObject value)
101101
PythonException.ThrowIfIsNull(op);
102102
return new PyFloat(op.Steal());
103103
}
104+
105+
public override TypeCode GetTypeCode() => TypeCode.Double;
104106
}
105107
}

src/runtime/PythonTypes/PyInt.cs

+2
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,7 @@ public string ToString(string format, IFormatProvider formatProvider)
230230
using var _ = Py.GIL();
231231
return ToBigInteger().ToString(format, formatProvider);
232232
}
233+
234+
public override TypeCode GetTypeCode() => TypeCode.Int64;
233235
}
234236
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
3+
namespace Python.Runtime;
4+
5+
public partial class PyObject : IConvertible
6+
{
7+
public virtual TypeCode GetTypeCode() => TypeCode.Object;
8+
9+
private T DoConvert<T>()
10+
{
11+
using var _ = Py.GIL();
12+
if (Converter.ToPrimitive(Reference, typeof(T), out object? result, setError: false))
13+
{
14+
return (T)result!;
15+
}
16+
else
17+
{
18+
throw new InvalidCastException();
19+
}
20+
}
21+
22+
public bool ToBoolean(IFormatProvider provider) => DoConvert<bool>();
23+
public byte ToByte(IFormatProvider provider) => DoConvert<byte>();
24+
public char ToChar(IFormatProvider provider) => DoConvert<char>();
25+
public short ToInt16(IFormatProvider provider) => DoConvert<short>();
26+
public int ToInt32(IFormatProvider provider) => DoConvert<int>();
27+
public long ToInt64(IFormatProvider provider) => DoConvert<long>();
28+
public sbyte ToSByte(IFormatProvider provider) => DoConvert<sbyte>();
29+
public ushort ToUInt16(IFormatProvider provider) => DoConvert<ushort>();
30+
public uint ToUInt32(IFormatProvider provider) => DoConvert<uint>();
31+
public ulong ToUInt64(IFormatProvider provider) => DoConvert<ulong>();
32+
33+
public float ToSingle(IFormatProvider provider) => DoConvert<float>();
34+
public double ToDouble(IFormatProvider provider) => DoConvert<double>();
35+
36+
public string ToString(IFormatProvider provider) => DoConvert<string>();
37+
38+
public DateTime ToDateTime(IFormatProvider provider) => throw new InvalidCastException();
39+
public decimal ToDecimal(IFormatProvider provider) => throw new InvalidCastException();
40+
41+
public object ToType(Type conversionType, IFormatProvider provider)
42+
{
43+
if (Converter.ToManaged(Reference, conversionType, out object? result, setError: false))
44+
{
45+
return result!;
46+
}
47+
else
48+
{
49+
throw new InvalidCastException();
50+
}
51+
}
52+
53+
}

src/runtime/PythonTypes/PyString.cs

+2
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,7 @@ public static bool IsStringType(PyObject value)
5959
{
6060
return Runtime.PyString_Check(value.obj);
6161
}
62+
63+
public override TypeCode GetTypeCode() => TypeCode.String;
6264
}
6365
}

tests/test_conversion.py

+7
Original file line numberDiff line numberDiff line change
@@ -670,3 +670,10 @@ def test_int_param_resolution_required():
670670
data = list(mri.MethodA(0x100000000, 10))
671671
assert len(data) == 10
672672
assert data[0] == 0
673+
674+
def test_iconvertible_conversion():
675+
change_type = System.Convert.ChangeType
676+
677+
assert 1024 == change_type(1024, System.Int32)
678+
assert 1024 == change_type(1024, System.Int64)
679+
assert 1024 == change_type(1024, System.Int16)

0 commit comments

Comments
 (0)