From a1e85e3f2adc25541566c55c9445b25f8bbaf2a0 Mon Sep 17 00:00:00 2001 From: eirannejad Date: Tue, 2 Apr 2024 14:52:07 -0700 Subject: [PATCH 1/2] do not include assembly-internal methods --- src/runtime/Types/ClassDerived.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/runtime/Types/ClassDerived.cs b/src/runtime/Types/ClassDerived.cs index 6771ad4ae..f3c8156ba 100644 --- a/src/runtime/Types/ClassDerived.cs +++ b/src/runtime/Types/ClassDerived.cs @@ -284,15 +284,16 @@ internal static Type CreateDerivedType(string typeName, ((m.Name.StartsWith("get_") || m.Name.StartsWith("set_")) && pyProperties.Contains(m.Name.Substring(4))); - return !alreadyOverriden + return m.Attributes.HasFlag(MethodAttributes.Virtual) + && !alreadyOverriden && !m.IsPrivate && !m.IsAssembly - && m.Attributes.HasFlag(MethodAttributes.Virtual) - && !m.Attributes.HasFlag(MethodAttributes.Final) - // overriding generic virtual methods is not supported - // so a call to that should be deferred to the base class method. - && !m.IsGenericMethod - && !(IsMethod(m) || IsMethod(m)); + // overriding generic virtual methods is not supported + // so a call to that should be deferred to the base class method. + && !m.IsGenericMethod + && !m.Attributes.HasFlag(MethodAttributes.Final) + && !m.Attributes.HasFlag(MethodAttributes.FamANDAssem) + && !(IsMethod(m) || IsMethod(m)); }) .Concat(baseInterfaces.SelectMany(x => x.GetMethods())) .ToList(); From aa0f5b350ba37b9d48b4438bd277c0a4f51b74a5 Mon Sep 17 00:00:00 2001 From: eirannejad Date: Tue, 2 Apr 2024 16:46:12 -0700 Subject: [PATCH 2/2] Fixed deriving from classes with assembly-internal methods --- src/runtime/Types/ClassDerived.cs | 6 +++++- src/testing/classtest.cs | 13 +++++++++++++ tests/test_class.py | 12 ++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/runtime/Types/ClassDerived.cs b/src/runtime/Types/ClassDerived.cs index f3c8156ba..b0483ad97 100644 --- a/src/runtime/Types/ClassDerived.cs +++ b/src/runtime/Types/ClassDerived.cs @@ -288,11 +288,15 @@ internal static Type CreateDerivedType(string typeName, && !alreadyOverriden && !m.IsPrivate && !m.IsAssembly + // FIXME: + // crude way of filtering out assembly-internal methods + // 'private protected' + // 'internal override' + && !m.IsFamilyAndAssembly // overriding generic virtual methods is not supported // so a call to that should be deferred to the base class method. && !m.IsGenericMethod && !m.Attributes.HasFlag(MethodAttributes.Final) - && !m.Attributes.HasFlag(MethodAttributes.FamANDAssem) && !(IsMethod(m) || IsMethod(m)); }) .Concat(baseInterfaces.SelectMany(x => x.GetMethods())) diff --git a/src/testing/classtest.cs b/src/testing/classtest.cs index 993afdfc9..a775d2abf 100644 --- a/src/testing/classtest.cs +++ b/src/testing/classtest.cs @@ -71,4 +71,17 @@ public static void TestObject(object obj) } } } + + public class ClassWithInternalBase + { + private protected virtual bool ThisShouldBeAccessibleFromPythonDerived() => false; + } + + public class ClassWithInternal : ClassWithInternalBase + { + private protected override bool ThisShouldBeAccessibleFromPythonDerived() + { + return base.ThisShouldBeAccessibleFromPythonDerived(); + } + } } diff --git a/tests/test_class.py b/tests/test_class.py index f63f05f4d..809d07418 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -329,3 +329,15 @@ def foo(): assert callable(System.String("foo")) == False assert callable(System.Action(foo)) == True + + +def test_derive_class_with_internal_virutal_method(): + """Test subclassing classes that have internal override methods work""" + + # this class definition should succeed + class MyClass(Test.ClassWithInternal): + def __init__(self): + pass + + MyClass() +