From df3b569eb1f8da0524d1322139aab520918f2a1b Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 23 Nov 2021 19:47:01 +0100 Subject: [PATCH 1/3] Fix enum codec A boxed enum value can't be casted directly to an integer, but using `System.Convert` functions instead works fine. --- src/runtime/Codecs/EnumPyIntCodec.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/runtime/Codecs/EnumPyIntCodec.cs b/src/runtime/Codecs/EnumPyIntCodec.cs index 7d33b34ce..34030ffb0 100644 --- a/src/runtime/Codecs/EnumPyIntCodec.cs +++ b/src/runtime/Codecs/EnumPyIntCodec.cs @@ -53,14 +53,7 @@ public bool TryDecode(PyObject pyObj, out T? value) var enumType = value.GetType(); if (!enumType.IsEnum) return null; - try - { - return new PyInt((long)value); - } - catch (InvalidCastException) - { - return new PyInt((ulong)value); - } + return new PyInt(Convert.ToInt64(value)); } private EnumPyIntCodec() { } From 4f070f24c3e7500b73d88d62a827f75be8f676ac Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 4 May 2022 08:33:32 +0200 Subject: [PATCH 2/3] Add unit test for enum encoder --- tests/test_codec.py | 68 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/tests/test_codec.py b/tests/test_codec.py index 9744d3856..6c74bd8eb 100644 --- a/tests/test_codec.py +++ b/tests/test_codec.py @@ -1,39 +1,53 @@ # -*- coding: utf-8 -*- """Test conversions using codecs from client python code""" -import clr -import System + import pytest import Python.Runtime +import Python.Test as Test from Python.Test import ListConversionTester, ListMember, CodecResetter -class int_iterable(): + +@pytest.fixture(autouse=True) +def reset(): + yield + CodecResetter.Reset() + + +class int_iterable: def __init__(self): self.counter = 0 + def __iter__(self): return self + def __next__(self): if self.counter == 3: raise StopIteration self.counter = self.counter + 1 return self.counter -class obj_iterable(): + +class obj_iterable: def __init__(self): self.counter = 0 + def __iter__(self): return self + def __next__(self): if self.counter == 3: raise StopIteration self.counter = self.counter + 1 return ListMember(self.counter, "Number " + str(self.counter)) + def test_iterable(): - """Test that a python iterable can be passed into a function that takes an IEnumerable""" + """Test that a python iterable can be passed into a function that takes an + IEnumerable""" - #Python.Runtime.Codecs.ListDecoder.Register() - #Python.Runtime.Codecs.SequenceDecoder.Register() + # Python.Runtime.Codecs.ListDecoder.Register() + # Python.Runtime.Codecs.SequenceDecoder.Register() Python.Runtime.Codecs.IterableDecoder.Register() ob = ListConversionTester() @@ -43,28 +57,58 @@ def test_iterable(): iterable2 = obj_iterable() assert 3 == ob.GetLength2(iterable2) - CodecResetter.Reset() def test_sequence(): Python.Runtime.Codecs.SequenceDecoder.Register() ob = ListConversionTester() - tup = (1,2,3) + tup = (1, 2, 3) assert 3 == ob.GetLength(tup) tup2 = (ListMember(1, "one"), ListMember(2, "two"), ListMember(3, "three")) assert 3 == ob.GetLength(tup2) - CodecResetter.Reset() def test_list(): Python.Runtime.Codecs.SequenceDecoder.Register() ob = ListConversionTester() - l = [1,2,3] + l = [1, 2, 3] assert 3 == ob.GetLength(l) l2 = [ListMember(1, "one"), ListMember(2, "two"), ListMember(3, "three")] assert 3 == ob.GetLength(l2) - CodecResetter.Reset() + +def test_enum(): + Python.Runtime.PyObjectConversions.RegisterEncoder( + Python.Runtime.Codecs.EnumPyIntCodec.Instance + ) + + assert Test.ByteEnum.Zero == 0 + assert Test.ByteEnum.One == 1 + assert Test.ByteEnum.Two == 2 + assert Test.SByteEnum.Zero == 0 + assert Test.SByteEnum.One == 1 + assert Test.SByteEnum.Two == 2 + assert Test.ShortEnum.Zero == 0 + assert Test.ShortEnum.One == 1 + assert Test.ShortEnum.Two == 2 + assert Test.UShortEnum.Zero == 0 + assert Test.UShortEnum.One == 1 + assert Test.UShortEnum.Two == 2 + assert Test.IntEnum.Zero == 0 + assert Test.IntEnum.One == 1 + assert Test.IntEnum.Two == 2 + assert Test.UIntEnum.Zero == 0 + assert Test.UIntEnum.One == 1 + assert Test.UIntEnum.Two == 2 + assert Test.LongEnum.Zero == 0 + assert Test.LongEnum.One == 1 + assert Test.LongEnum.Two == 2 + assert Test.ULongEnum.Zero == 0 + assert Test.ULongEnum.One == 1 + assert Test.ULongEnum.Two == 2 + assert Test.LongEnum.Max == 9223372036854775807 + assert Test.LongEnum.Min == -9223372036854775808 + assert int(Test.ULongEnum.Max) == 18446744073709551615 From 7d6e27a23ec88138ada829f50e473cea394df189 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 4 May 2022 08:40:50 +0200 Subject: [PATCH 3/3] Allow conversion of UInt64 based enums --- src/runtime/Codecs/EnumPyIntCodec.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/runtime/Codecs/EnumPyIntCodec.cs b/src/runtime/Codecs/EnumPyIntCodec.cs index 34030ffb0..42f5eb1b2 100644 --- a/src/runtime/Codecs/EnumPyIntCodec.cs +++ b/src/runtime/Codecs/EnumPyIntCodec.cs @@ -53,7 +53,14 @@ public bool TryDecode(PyObject pyObj, out T? value) var enumType = value.GetType(); if (!enumType.IsEnum) return null; - return new PyInt(Convert.ToInt64(value)); + try + { + return new PyInt(Convert.ToInt64(value)); + } + catch (OverflowException) + { + return new PyInt(Convert.ToUInt64(value)); + } } private EnumPyIntCodec() { }