Skip to content

Commit 22d07dd

Browse files
koubaaMohamed Koubaa
and
Mohamed Koubaa
authored
custom repr for enum values (pythonnet#2239)
Examples: <DayOfWeek.Monday: 1> <FlagsEnum.Two, Five: 0x00000007> <FlagsEnum.8: 0x00000008> --------- Co-authored-by: Mohamed Koubaa <[email protected]>
1 parent 171cee4 commit 22d07dd

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
99

1010
### Added
1111

12+
- use enum name in repr
13+
1214
### Changed
1315

1416
### Fixed

src/runtime/Types/ClassObject.cs

+51
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
22
using System.Diagnostics;
3+
using System.Globalization;
34
using System.Linq;
45
using System.Reflection;
6+
using System.Runtime.InteropServices;
57
using System.Runtime.Serialization;
68

79
namespace Python.Runtime
@@ -47,6 +49,55 @@ internal NewReference GetDocString()
4749
return Runtime.PyString_FromString(str);
4850
}
4951

52+
private static string ConvertFlags(Enum value)
53+
{
54+
Type primitiveType = value.GetType().GetEnumUnderlyingType();
55+
string format = "X" + (Marshal.SizeOf(primitiveType) * 2).ToString(CultureInfo.InvariantCulture);
56+
var primitive = (IFormattable)Convert.ChangeType(value, primitiveType);
57+
return "0x" + primitive.ToString(format, null);
58+
59+
}
60+
61+
private static string ConvertValue(Enum value)
62+
{
63+
Type primitiveType = value.GetType().GetEnumUnderlyingType();
64+
return Convert.ChangeType(value, primitiveType).ToString()!;
65+
}
66+
67+
/// <summary>
68+
/// given an enum, write a __repr__ string formatted in the same
69+
/// way as a python repr string. Something like:
70+
/// '&lt;Color.GREEN: 2&gt;';
71+
/// with a binary value for [Flags] enums
72+
/// </summary>
73+
/// <param name="inst">Instace of the enum object</param>
74+
/// <returns></returns>
75+
private static string GetEnumReprString(Enum inst)
76+
{
77+
var obType = inst.GetType();
78+
79+
string strValue2 = obType.IsFlagsEnum() ? ConvertFlags(inst) : ConvertValue(inst);
80+
81+
var repr = $"<{obType.Name}.{inst}: {strValue2}>";
82+
return repr;
83+
}
84+
85+
/// <summary>
86+
/// ClassObject __repr__ implementation.
87+
/// </summary>
88+
public new static NewReference tp_repr(BorrowedReference ob)
89+
{
90+
if (GetManagedObject(ob) is not CLRObject co)
91+
{
92+
return Exceptions.RaiseTypeError("invalid object");
93+
}
94+
if (co.inst.GetType().IsEnum)
95+
{
96+
return Runtime.PyString_FromString(GetEnumReprString((Enum)co.inst));
97+
}
98+
99+
return ClassBase.tp_repr(ob);
100+
}
50101

51102
/// <summary>
52103
/// Implements __new__ for reflected classes and value types.

tests/test_enum.py

+10
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,16 @@ def test_enum_undefined_value():
143143
Test.FieldTest().EnumField = Test.ShortEnum(20, True)
144144

145145

146+
def test_enum_repr():
147+
"""Test enumeration repr."""
148+
from System import DayOfWeek
149+
150+
assert repr(DayOfWeek.Monday) == "<DayOfWeek.Monday: 1>"
151+
152+
assert repr(Test.FlagsEnum(7)) == "<FlagsEnum.Two, Five: 0x00000007>"
153+
assert repr(Test.FlagsEnum(8)) == "<FlagsEnum.8: 0x00000008>"
154+
155+
146156
def test_enum_conversion():
147157
"""Test enumeration conversion."""
148158
ob = Test.FieldTest()

0 commit comments

Comments
 (0)