Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e8ea7a6
1776 Inherit Generic Virtual Method Bug: Unit Test
rmadsen-ks Apr 27, 2022
691f207
1776 Inherit Generic Virtual Method Bug: Fix
rmadsen-ks Apr 28, 2022
e27ad8c
1774-ClassWithoutnamespace
rmadsen-ks Apr 29, 2022
f1fa696
better support for multiple inheritance
rmadsen-ks May 3, 2022
6f0b354
Fixed issue with protected constructors and classes with no constructor
rmadsen-ks May 3, 2022
3963621
Added supporr for class/property/method attributes.
rmadsen-ks May 5, 2022
4e0d003
- Expanded the way attributes amy be added
rmadsen-ks May 5, 2022
ea598a2
added support for creating abstract classes using a __clr_abstract__ …
rmadsen-ks May 6, 2022
d6abbb2
Improved AttributeError when looking for a symbol that does not exist…
rmadsen-ks May 24, 2022
2a84675
Added test to detect an issue with object construction.
rmadsen-ks Jun 28, 2022
172c642
got rid of a few deprecation warnings that pollute GitHub code review
lostmsu Jun 30, 2022
32d15eb
docs: Fix a few typos
timgates42 Jul 16, 2022
9eaf35f
Added support for marking properties with python types.
rmadsen-ks Sep 2, 2022
9ed94f6
Fixed issue calling base-base class implementation of methods.
rmadsen-ks Sep 2, 2022
da146d9
Merged with Pythonnet 3.0 RC.6.
rmadsen-ks Oct 28, 2022
b280b1b
Fixed bug related to converting number to a string
rmadsen-ks Oct 28, 2022
61c5d99
Added support for Python 3.11.
rmadsen-ks Oct 28, 2022
ed89819
Merge remote-tracking branch 'github/master'
rmadsen-ks Nov 14, 2023
56c8a39
Merge branch 'master' of github.com:pythonnet/pythonnet
rmadsen-ks Nov 14, 2023
e986114
Merge remote-tracking branch 'github/master'
rmadsen-ks Aug 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge remote-tracking branch 'github/master'
  • Loading branch information
rmadsen-ks committed Nov 14, 2023
commit ed898197dfafc2787c24ea1485b38472c66dfd45
1 change: 1 addition & 0 deletions src/python_tests_runner/PythonTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static IEnumerable<string[]> PythonTestCases()
// Add the test that you want to debug here.
yield return new[] { "test_indexer", "test_boolean_indexer" };
yield return new[] { "test_delegate", "test_bool_delegate" };
yield return new[] { "test_subclass", "test_implement_interface_and_class" };
yield return new[] { "test_subclass", "test_virtual_generic_method" };
yield return new[] { "test_subclass", "test_interface_and_class_impl2" };
yield return new[] { "test_subclass", "test_class_with_attributes" };
Expand Down
7 changes: 2 additions & 5 deletions src/runtime/Native/TypeOffset311.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Auto-generated by geninterop.py.
// Auto-generated by geninterop.py.
// DO NOT MODIFY BY HAND.

// Python 3.11: ABI flags: ''
Expand All @@ -21,10 +21,7 @@ namespace Python.Runtime
[StructLayout(LayoutKind.Sequential)]
internal class TypeOffset311 : GeneratedTypeOffsets, ITypeOffsets
{
public TypeOffset311()
{

}
public TypeOffset311() { }
// Auto-generated from PyHeapTypeObject in Python.h
public int ob_refcnt { get; private set; }
public int ob_type { get; private set; }
Expand Down
12 changes: 5 additions & 7 deletions src/runtime/TypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ static PyTuple GetBaseTypeTuple(Type clrType)
return new PyTuple(bases);
}

internal static NewReference CreateSubType(BorrowedReference py_name, IEnumerable<ClassBase> py_base_type, IEnumerable<Type> interfaces, BorrowedReference dictRef)
internal static NewReference CreateSubType(BorrowedReference py_name, ClassBase py_base_type, IList<Type> interfaces, BorrowedReference dictRef)
{
// Utility to create a subtype of a managed type with the ability for the
// a python subtype able to override the managed implementation
Expand Down Expand Up @@ -415,12 +415,10 @@ internal static NewReference CreateSubType(BorrowedReference py_name, IEnumerabl
}

// create the new managed type subclassing the base managed type
var baseClass = py_base_type.FirstOrDefault();

return ReflectedClrType.CreateSubclass(baseClass, interfaces, name,
ns: (string?)namespaceStr,
assembly: (string?)assembly,
dict: dictRef);
return ReflectedClrType.CreateSubclass(py_base_type, interfaces, name,
ns: (string?)namespaceStr,
assembly: (string?)assembly,
dict: dictRef);
}

internal static IntPtr WriteMethodDef(IntPtr mdef, IntPtr name, IntPtr func, PyMethodFlags flags, IntPtr doc)
Expand Down
13 changes: 8 additions & 5 deletions src/runtime/Types/ClassDerived.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ static CustomAttributeBuilder AddAttribute(PyObject attr)
/// </summary>
internal static Type CreateDerivedType(string name,
Type baseType,
IEnumerable<Type> interfaces2,
IList<Type> typeInterfaces,
BorrowedReference py_dict,
string? namespaceStr,
string? assemblyName,
Expand All @@ -276,7 +276,7 @@ internal static Type CreateDerivedType(string name,

Type baseClass = baseType;
var interfaces = new HashSet<Type> { typeof(IPythonDerivedType) };
foreach(var t in interfaces2) interfaces.Add(t);
foreach(var t in interfaces) interfaces.Add(t);
// if the base type is an interface then use System.Object as the base class
// and add the base type to the list of interfaces this new class will implement.
if (baseType.IsInterface)
Expand Down Expand Up @@ -342,13 +342,16 @@ internal static Type CreateDerivedType(string name,
}
}

// override any virtual methods not already overridden by the properties above
// override any virtual not already overridden by the properties above
// also override any interface method.
var methods = baseType.GetMethods().Concat(interfaces.SelectMany(x => x.GetMethods()));
var virtualMethods = new HashSet<string>();
foreach (MethodInfo method in methods)
{
if (!method.Attributes.HasFlag(MethodAttributes.Virtual)
|| method.Attributes.HasFlag(MethodAttributes.Final)
if (!method.Attributes.HasFlag(MethodAttributes.Virtual) |
method.Attributes.HasFlag(MethodAttributes.Final)
// overriding generic virtual methods is not supported
// so a call to that should be deferred to the base class method.
|| method.IsGenericMethod)
{
continue;
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/Types/ManagedType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ protected static void ClearObjectDict(BorrowedReference ob)
{
BorrowedReference type = Runtime.PyObject_TYPE(ob);
int instanceDictOffset = Util.ReadInt32(type, TypeOffset.tp_dictoffset);
//Debug.Assert(instanceDictOffset > 0);
// Debug.Assert(instanceDictOffset > 0);
// Python 3.11, sometimes this dict is less than zero.
if(instanceDictOffset > 0)
if (instanceDictOffset > 0)
Runtime.Py_CLEAR(ob, instanceDictOffset);
}

Expand Down
81 changes: 51 additions & 30 deletions src/runtime/Types/MetaType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,47 +85,66 @@ public static NewReference tp_new(BorrowedReference tp, BorrowedReference args,
// Extract interface types and base class types.
var interfaces = new List<Type>();

// More than one base type case be declared, but an exception will be thrown
// if more than one is a class/not an interface.
var baseTypes = new List<ClassBase>();

List<Type> interfaces = new List<Type>();
List<ClassBase> baseType = new List<ClassBase>();

var cnt = Runtime.PyTuple_GetSize(bases);
var baseClassCount = Runtime.PyTuple_Size(bases);
if (baseClassCount == 0)
{
return Exceptions.RaiseTypeError("zero base classes ");
}

for (uint i = 0; i < cnt; i++)
for (nint i = 0; i < baseClassCount; i++)
{
var base_type2 = Runtime.PyTuple_GetItem(bases, (int)i);
var cb2 = (ClassBase) GetManagedObject(base_type2);
if (cb2 != null)
var baseTypeIt = Runtime.PyTuple_GetItem(bases, (int)i);

if (GetManagedObject(baseTypeIt) is ClassBase classBaseIt)
{
if (!classBaseIt.type.Valid)
{
return Exceptions.RaiseTypeError("Invalid type used as a super type.");
}
if (classBaseIt.type.Value.IsInterface)
{
interfaces.Add(classBaseIt.type.Value);
}
else
{
baseTypes.Add(classBaseIt);
}
}
else
{
if (cb2.type.Valid && cb2.type.Value.IsInterface)
interfaces.Add(cb2.type.Value);
else baseType.Add(cb2);
return Exceptions.RaiseTypeError("Non .NET type used as super class for meta type. This is not supported.");
}
}

if (baseType.Count == 0)
// if the base type count is 0, there might still be interfaces to implement.
if (baseTypes.Count == 0)
{
baseType.Add(new ClassBase(typeof(object)));
baseTypes.Add(new ClassBase(typeof(object)));
}


if (baseType.Count > 1)
// Multiple inheritance is not supported, unless the other types are interfaces
if (baseTypes.Count > 1)
{
return Exceptions.RaiseTypeError("zero base classes ");
var types = string.Join(", ", baseTypes.Select(baseType => baseType.type.Value));
return Exceptions.RaiseTypeError($"Multiple inheritance with managed classes cannot be used. Types: {types} ");
}

/*
BorrowedReference mt = Runtime.PyObject_TYPE(baseType);

if (!(mt == PyCLRMetaType || mt == Runtime.PyTypeType))
// check if the list of interfaces contains no duplicates.
if (interfaces.Distinct().Count() != interfaces.Count)
{
return Exceptions.RaiseTypeError("invalid metatype");
}*/
// generate a string containing the problematic types.
var duplicateTypes = interfaces.GroupBy(type => type)
.Where(typeGroup => typeGroup.Count() > 1)
.Select(typeGroup => typeGroup.Key);
var duplicateTypesString = string.Join(", ", duplicateTypes);

// Ensure that the reflected type is appropriate for subclassing,
// disallowing subclassing of delegates, enums and array types.
return Exceptions.RaiseTypeError($"An interface can only be implemented once. Duplicate types: {duplicateTypesString}");
}

var cb = baseType.First();
var cb = baseTypes[0];
try
{
if (!cb.CanSubclass())
Expand All @@ -150,11 +169,11 @@ public static NewReference tp_new(BorrowedReference tp, BorrowedReference args,
// into python.
if (null != dict)
{
var btt = baseType.FirstOrDefault().type.ValueOrNull;
var btt = baseTypes.FirstOrDefault().type.ValueOrNull;
var ctor = btt?.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(x => x.GetParameters().Any() == false);
using var clsDict = new PyDict(dict);

if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__")
|| (ctor != null))
{
Expand All @@ -163,9 +182,11 @@ public static NewReference tp_new(BorrowedReference tp, BorrowedReference args,
clsDict["__namespace__"] =
(clsDict["__module__"].ToString()).ToPython();
}
return TypeManager.CreateSubType(name, baseType, interfaces, clsDict);

return TypeManager.CreateSubType(name, baseTypes[0], interfaces, clsDict);

}

}

var base_type = Runtime.PyTuple_GetItem(bases, 0);
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/Types/ReflectedClrType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ internal void Restore(ClassBase cb)
TypeManager.InitializeClass(this, cb, cb.type.Value);
}

internal static NewReference CreateSubclass(ClassBase baseClass, IEnumerable<Type> interfaces,
internal static NewReference CreateSubclass(ClassBase baseClass, IList<Type> interfaces,
string name, string? assembly, string? ns,
BorrowedReference dict)
{
Expand Down
11 changes: 0 additions & 11 deletions src/testing/classtest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,4 @@ public ClassCtorTest2(string v)
internal class InternalClass
{
}

public class SimpleClass
{
public static void TestObject(object obj)
{
if ((!(obj is ISayHello1 && obj is SimpleClass)))
{
throw new Exception("Expected ISayHello and SimpleClass instance");
}
}
}
}
30 changes: 28 additions & 2 deletions tests/test_subclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
from System.ComponentModel import (Browsable, BrowsableAttribute)
from System.Threading import (CancellationToken)
import pytest
from Python.Test import (IInterfaceTest, SubClassTest, EventArgsTest,
FunctionsTest, GenericVirtualMethodTest, ISimpleInterface, SimpleClass, TestAttribute, TestAttributeAttribute, ISimpleInterface2)
from Python.Test import (IInterfaceTest, SubClassTest, EventArgsTest, FunctionsTest,IGenericInterface, GenericVirtualMethodTest, ISimpleInterface, SimpleClass, TestAttribute, TestAttributeAttribute, ISimpleInterface2, ISayHello1)
import Python.Test
from System.Collections.Generic import List

Expand Down Expand Up @@ -500,3 +499,30 @@ def IncrementThing(self):
print(x.CallIncrementThing())



def test_generic_interface():
from System import Int32
from Python.Test import GenericInterfaceUser, SpecificInterfaceUser

GenericInterfaceImpl = interface_generic_class_fixture(test_generic_interface.__name__)

obj = GenericInterfaceImpl()
SpecificInterfaceUser(obj, Int32(0))
GenericInterfaceUser[Int32](obj, Int32(0))

def test_virtual_generic_method():
class OverloadingSubclass(GenericVirtualMethodTest):
__namespace__ = "test_virtual_generic_method_cls"
class OverloadingSubclass2(OverloadingSubclass):
__namespace__ = "test_virtual_generic_method_cls"
obj = OverloadingSubclass()
assert obj.VirtMethod[int](5) == 5
obj = OverloadingSubclass2()
assert obj.VirtMethod[int](5) == 5

def test_implement_interface_and_class():
class DualSubClass0(ISayHello1, SimpleClass):
__namespace__ = "Test"
def SayHello(self):
return "hello"
obj = DualSubClass0()
You are viewing a condensed version of this merge commit. You can view the full changes here.