diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs index f8e108f41..647cec3ed 100644 --- a/src/runtime/classmanager.cs +++ b/src/runtime/classmanager.cs @@ -346,8 +346,7 @@ private static ClassInfo GetClassInfo(Type type, ClassBase impl) } } - // only [Flags] enums support bitwise operations - if (type.IsEnum && type.IsFlagsEnum()) + if (type.IsEnum) { var opsImpl = typeof(EnumOps<>).MakeGenericType(type); foreach (var op in opsImpl.GetMethods(OpsHelper.BindingFlags)) @@ -355,6 +354,17 @@ private static ClassInfo GetClassInfo(Type type, ClassBase impl) local.Add(op.Name); } info = info.Concat(opsImpl.GetMethods(OpsHelper.BindingFlags)).ToArray(); + + // only [Flags] enums support bitwise operations + if (type.IsFlagsEnum()) + { + opsImpl = typeof(FlagEnumOps<>).MakeGenericType(type); + foreach (var op in opsImpl.GetMethods(OpsHelper.BindingFlags)) + { + local.Add(op.Name); + } + info = info.Concat(opsImpl.GetMethods(OpsHelper.BindingFlags)).ToArray(); + } } // Now again to filter w/o losing overloaded member info diff --git a/src/runtime/native/ITypeOffsets.cs b/src/runtime/native/ITypeOffsets.cs index 0829e5bc9..2c4fdf59a 100644 --- a/src/runtime/native/ITypeOffsets.cs +++ b/src/runtime/native/ITypeOffsets.cs @@ -21,6 +21,7 @@ interface ITypeOffsets int nb_multiply { get; } int nb_true_divide { get; } int nb_and { get; } + int nb_int { get; } int nb_or { get; } int nb_xor { get; } int nb_lshift { get; } diff --git a/src/runtime/native/TypeOffset.cs b/src/runtime/native/TypeOffset.cs index 3f97b0f45..a1bae8253 100644 --- a/src/runtime/native/TypeOffset.cs +++ b/src/runtime/native/TypeOffset.cs @@ -30,6 +30,7 @@ static partial class TypeOffset internal static int nb_and { get; private set; } internal static int nb_or { get; private set; } internal static int nb_xor { get; private set; } + internal static int nb_int { get; private set; } internal static int nb_lshift { get; private set; } internal static int nb_rshift { get; private set; } internal static int nb_remainder { get; private set; } diff --git a/src/runtime/operatormethod.cs b/src/runtime/operatormethod.cs index 035198f3e..abe6ded1a 100644 --- a/src/runtime/operatormethod.cs +++ b/src/runtime/operatormethod.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Reflection; -using System.Runtime.InteropServices; using System.Text; namespace Python.Runtime @@ -51,6 +51,8 @@ static OperatorMethod() ["op_OnesComplement"] = new SlotDefinition("__invert__", TypeOffset.nb_invert), ["op_UnaryNegation"] = new SlotDefinition("__neg__", TypeOffset.nb_negative), ["op_UnaryPlus"] = new SlotDefinition("__pos__", TypeOffset.nb_positive), + + ["__int__"] = new SlotDefinition("__int__", TypeOffset.nb_int), }; ComparisonOpMap = new Dictionary { @@ -97,14 +99,11 @@ public static bool IsComparisonOp(MethodBase method) /// public static void FixupSlots(BorrowedReference pyType, Type clrType) { - const BindingFlags flags = BindingFlags.Public | BindingFlags.Static; Debug.Assert(_opType != null); - var staticMethods = - clrType.IsEnum ? typeof(EnumOps<>).MakeGenericType(clrType).GetMethods(flags) - : clrType.GetMethods(flags); + var operatorCandidates = GetOperatorCandidates(clrType); - foreach (var method in staticMethods) + foreach (var method in operatorCandidates) { // We only want to override slots for operators excluding // comparison operators, which are handled by ClassBase.tp_richcompare. @@ -124,6 +123,18 @@ public static void FixupSlots(BorrowedReference pyType, Type clrType) } } + static IEnumerable GetOperatorCandidates(Type clrType) + { + const BindingFlags flags = BindingFlags.Public | BindingFlags.Static; + if (clrType.IsEnum) + { + return typeof(EnumOps<>).MakeGenericType(clrType).GetMethods(flags) + .Concat(typeof(FlagEnumOps<>).MakeGenericType(clrType).GetMethods(flags)); + } + + return clrType.GetMethods(flags); + } + public static string GetPyMethodName(string clrName) { if (OpMethodMap.ContainsKey(clrName)) diff --git a/src/runtime/opshelper.cs b/src/runtime/opshelper.cs index 59f7704b7..ab623f3de 100644 --- a/src/runtime/opshelper.cs +++ b/src/runtime/opshelper.cs @@ -38,7 +38,7 @@ public static Expression EnumUnderlyingValue(Expression enumValue) internal class OpsAttribute: Attribute { } [Ops] - internal static class EnumOps where T : Enum + internal static class FlagEnumOps where T : Enum { static readonly Func and = BinaryOp(Expression.And); static readonly Func or = BinaryOp(Expression.Or); @@ -74,4 +74,16 @@ static Func UnaryOp(Func op) }); } } + + [Ops] + internal static class EnumOps where T : Enum + { + [ForbidPythonThreads] +#pragma warning disable IDE1006 // Naming Styles - must match Python + public static PyInt __int__(T value) +#pragma warning restore IDE1006 // Naming Styles + => typeof(T).GetEnumUnderlyingType() == typeof(UInt64) + ? new PyInt(Convert.ToUInt64(value)) + : new PyInt(Convert.ToInt64(value)); + } } diff --git a/src/testing/enumtest.cs b/src/testing/enumtest.cs index de5d8f5ee..f7d07339f 100644 --- a/src/testing/enumtest.cs +++ b/src/testing/enumtest.cs @@ -72,7 +72,9 @@ public enum LongEnum : long Two, Three, Four, - Five + Five, + Max = long.MaxValue, + Min = long.MinValue, } public enum ULongEnum : ulong @@ -82,7 +84,8 @@ public enum ULongEnum : ulong Two, Three, Four, - Five + Five, + Max = ulong.MaxValue, } [Flags] diff --git a/tests/test_enum.py b/tests/test_enum.py index 1f0711a94..b2eb0569f 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -87,6 +87,15 @@ def test_ulong_enum(): assert Test.ULongEnum.Two == Test.ULongEnum(2) +def test_long_enum_to_int(): + assert int(Test.LongEnum.Max) == 9223372036854775807 + assert int(Test.LongEnum.Min) == -9223372036854775808 + + +def test_ulong_enum_to_int(): + assert int(Test.ULongEnum.Max) == 18446744073709551615 + + def test_instantiate_enum_fails(): """Test that instantiation of an enum class fails.""" from System import DayOfWeek 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