Repository: pythonnet/pythonnet (language: python)

Issue:
Enum __repr__ string could be improved
### Environment

-   Pythonnet version: 3.1.0
-   Python version: 3.11
-   Operating System: Windows
-   .NET Runtime: .NET FW

### Details

- Many .NET APIs use enum values as method return types or properties. In an interactive shell, it may be useful to see the enum value with `repr`. This is how IronPython seems to do things:

**IronPython 2.7.4** (2.7.0.40) on .NET 4.0.30319.42000 (64-bit)
Type "help", "copyright", "credits" or "license" for more information.
>>> import System
>>> System.DayOfWeek.Monday
System.DayOfWeek.Monday

**Python 3.11.4** (tags/v3.11.4:d2340ef, Jun  7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr; import System
>>> System.DayOfWeek.Monday
<System.DayOfWeek object at 0x0000024D5BAC7300>



Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4ba0b935c..fb13982e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
 
 ### Added
 
+- use enum name in repr
+
 ### Changed
 
 ### Fixed
diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs
index cc42039e8..f0585ffa6 100644
--- a/src/runtime/Types/ClassObject.cs
+++ b/src/runtime/Types/ClassObject.cs
@@ -1,7 +1,9 @@
 using System;
 using System.Diagnostics;
+using System.Globalization;
 using System.Linq;
 using System.Reflection;
+using System.Runtime.InteropServices;
 using System.Runtime.Serialization;
 
 namespace Python.Runtime
@@ -47,6 +49,55 @@ internal NewReference GetDocString()
             return Runtime.PyString_FromString(str);
         }
 
+        private static string ConvertFlags(Enum value)
+        {
+            Type primitiveType = value.GetType().GetEnumUnderlyingType();
+            string format = "X" + (Marshal.SizeOf(primitiveType) * 2).ToString(CultureInfo.InvariantCulture);
+            var primitive = (IFormattable)Convert.ChangeType(value, primitiveType);
+            return "0x" + primitive.ToString(format, null);
+
+        }
+
+        private static string ConvertValue(Enum value)
+        {
+            Type primitiveType = value.GetType().GetEnumUnderlyingType();
+            return Convert.ChangeType(value, primitiveType).ToString()!;
+        }
+
+        /// <summary>
+        /// given an enum, write a __repr__ string formatted in the same
+        /// way as a python repr string. Something like:
+        ///   '&lt;Color.GREEN: 2&gt;';
+        /// with a binary value for [Flags] enums
+        /// </summary>
+        /// <param name="inst">Instace of the enum object</param>
+        /// <returns></returns>
+        private static string GetEnumReprString(Enum inst)
+        {
+            var obType = inst.GetType();
+
+            string strValue2 = obType.IsFlagsEnum() ? ConvertFlags(inst) : ConvertValue(inst);
+
+            var repr = $"<{obType.Name}.{inst}: {strValue2}>";
+            return repr;
+        }
+
+        /// <summary>
+        /// ClassObject __repr__ implementation.
+        /// </summary>
+        public new static NewReference tp_repr(BorrowedReference ob)
+        {
+            if (GetManagedObject(ob) is not CLRObject co)
+            {
+                return Exceptions.RaiseTypeError("invalid object");
+            }
+            if (co.inst.GetType().IsEnum)
+            {
+                return Runtime.PyString_FromString(GetEnumReprString((Enum)co.inst));
+            }
+
+            return ClassBase.tp_repr(ob);
+        }
 
         /// <summary>
         /// Implements __new__ for reflected classes and value types.


Test patch:
diff --git a/tests/test_enum.py b/tests/test_enum.py
index f24f95b36..3d3edba10 100644
--- a/tests/test_enum.py
+++ b/tests/test_enum.py
@@ -143,6 +143,16 @@ def test_enum_undefined_value():
     Test.FieldTest().EnumField = Test.ShortEnum(20, True)
 
 
+def test_enum_repr():
+    """Test enumeration repr."""
+    from System import DayOfWeek
+
+    assert repr(DayOfWeek.Monday) == "<DayOfWeek.Monday: 1>"
+
+    assert repr(Test.FlagsEnum(7)) == "<FlagsEnum.Two, Five: 0x00000007>"
+    assert repr(Test.FlagsEnum(8)) == "<FlagsEnum.8: 0x00000008>"
+
+
 def test_enum_conversion():
     """Test enumeration conversion."""
     ob = Test.FieldTest()