From 9a0ceb698ea83ef726e52e84849ff62c6f5ef053 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Sun, 10 Apr 2022 18:12:51 +0200 Subject: [PATCH] Implement IConvertible interface on PyObject --- src/runtime/Converter.cs | 2 +- src/runtime/PythonTypes/PyFloat.cs | 2 + src/runtime/PythonTypes/PyInt.cs | 2 + .../PythonTypes/PyObject.IConvertible.cs | 53 +++++++++++++++++++ src/runtime/PythonTypes/PyString.cs | 2 + tests/test_conversion.py | 7 +++ 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/runtime/PythonTypes/PyObject.IConvertible.cs diff --git a/src/runtime/Converter.cs b/src/runtime/Converter.cs index a90f31513..a99961aaa 100644 --- a/src/runtime/Converter.cs +++ b/src/runtime/Converter.cs @@ -550,7 +550,7 @@ internal static int ToInt32(BorrowedReference value) /// /// Convert a Python value to an instance of a primitive managed type. /// - private static bool ToPrimitive(BorrowedReference value, Type obType, out object? result, bool setError) + internal static bool ToPrimitive(BorrowedReference value, Type obType, out object? result, bool setError) { result = null; if (obType.IsEnum) diff --git a/src/runtime/PythonTypes/PyFloat.cs b/src/runtime/PythonTypes/PyFloat.cs index 7fb9e8f4d..10104c10f 100644 --- a/src/runtime/PythonTypes/PyFloat.cs +++ b/src/runtime/PythonTypes/PyFloat.cs @@ -101,5 +101,7 @@ public static PyFloat AsFloat(PyObject value) PythonException.ThrowIfIsNull(op); return new PyFloat(op.Steal()); } + + public override TypeCode GetTypeCode() => TypeCode.Double; } } diff --git a/src/runtime/PythonTypes/PyInt.cs b/src/runtime/PythonTypes/PyInt.cs index 3dcc6ddb2..6b3dbf210 100644 --- a/src/runtime/PythonTypes/PyInt.cs +++ b/src/runtime/PythonTypes/PyInt.cs @@ -230,5 +230,7 @@ public string ToString(string format, IFormatProvider formatProvider) using var _ = Py.GIL(); return ToBigInteger().ToString(format, formatProvider); } + + public override TypeCode GetTypeCode() => TypeCode.Int64; } } diff --git a/src/runtime/PythonTypes/PyObject.IConvertible.cs b/src/runtime/PythonTypes/PyObject.IConvertible.cs new file mode 100644 index 000000000..503d3cab4 --- /dev/null +++ b/src/runtime/PythonTypes/PyObject.IConvertible.cs @@ -0,0 +1,53 @@ +using System; + +namespace Python.Runtime; + +public partial class PyObject : IConvertible +{ + public virtual TypeCode GetTypeCode() => TypeCode.Object; + + private T DoConvert() + { + using var _ = Py.GIL(); + if (Converter.ToPrimitive(Reference, typeof(T), out object? result, setError: false)) + { + return (T)result!; + } + else + { + throw new InvalidCastException(); + } + } + + public bool ToBoolean(IFormatProvider provider) => DoConvert(); + public byte ToByte(IFormatProvider provider) => DoConvert(); + public char ToChar(IFormatProvider provider) => DoConvert(); + public short ToInt16(IFormatProvider provider) => DoConvert(); + public int ToInt32(IFormatProvider provider) => DoConvert(); + public long ToInt64(IFormatProvider provider) => DoConvert(); + public sbyte ToSByte(IFormatProvider provider) => DoConvert(); + public ushort ToUInt16(IFormatProvider provider) => DoConvert(); + public uint ToUInt32(IFormatProvider provider) => DoConvert(); + public ulong ToUInt64(IFormatProvider provider) => DoConvert(); + + public float ToSingle(IFormatProvider provider) => DoConvert(); + public double ToDouble(IFormatProvider provider) => DoConvert(); + + public string ToString(IFormatProvider provider) => DoConvert(); + + public DateTime ToDateTime(IFormatProvider provider) => throw new InvalidCastException(); + public decimal ToDecimal(IFormatProvider provider) => throw new InvalidCastException(); + + public object ToType(Type conversionType, IFormatProvider provider) + { + if (Converter.ToManaged(Reference, conversionType, out object? result, setError: false)) + { + return result!; + } + else + { + throw new InvalidCastException(); + } + } + +} \ No newline at end of file diff --git a/src/runtime/PythonTypes/PyString.cs b/src/runtime/PythonTypes/PyString.cs index cdd45e2c3..d54397fcf 100644 --- a/src/runtime/PythonTypes/PyString.cs +++ b/src/runtime/PythonTypes/PyString.cs @@ -59,5 +59,7 @@ public static bool IsStringType(PyObject value) { return Runtime.PyString_Check(value.obj); } + + public override TypeCode GetTypeCode() => TypeCode.String; } } diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 341b11b90..4de286b14 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -670,3 +670,10 @@ def test_int_param_resolution_required(): data = list(mri.MethodA(0x100000000, 10)) assert len(data) == 10 assert data[0] == 0 + +def test_iconvertible_conversion(): + change_type = System.Convert.ChangeType + + assert 1024 == change_type(1024, System.Int32) + assert 1024 == change_type(1024, System.Int64) + assert 1024 == change_type(1024, System.Int16) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy