Skip to content

Commit 072346a

Browse files
Fix method overload snakename handling (#89)
* Fix method overload snakename handling - Fix method overload snakename handling and resolution, expanding unit tests to cover missing case - Minor cleanup * Version bump to 2.0.34 * Push fake snakenamed methods at the end * Fix methods overloads parameter type matching --------- Co-authored-by: Jhonathan Abreu <[email protected]>
1 parent d94b7e4 commit 072346a

15 files changed

+491
-274
lines changed

src/embed_tests/ClassManagerTests.cs

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,21 @@ public int another_int_property()
710710
return 654;
711711
}
712712

713+
public dynamic a(AlreadyDefinedSnakeCaseMemberTestBaseClass a)
714+
{
715+
throw new Exception("a(AlreadyDefinedSnakeCaseMemberTestBaseClass)");
716+
}
717+
718+
public int a()
719+
{
720+
throw new Exception("a()");
721+
}
722+
723+
public int get_value()
724+
{
725+
throw new Exception("get_value()");
726+
}
727+
713728
public virtual int get_value(int x)
714729
{
715730
throw new Exception("get_value(int x)");
@@ -752,6 +767,14 @@ private class AlreadyDefinedSnakeCaseMemberTestDerivedClass : AlreadyDefinedSnak
752767

753768
public override int AnotherIntProperty { get; set; } = 222;
754769

770+
public int A()
771+
{
772+
throw new Exception("A()");
773+
}
774+
public PyObject A(PyObject a)
775+
{
776+
throw new Exception("A(PyObject)");
777+
}
755778
public override int get_value(int x)
756779
{
757780
throw new Exception("override get_value(int x)");
@@ -779,10 +802,35 @@ public override int GetValue2(int x)
779802
// 2 int args, binds to the snake-cased overriden GetValue(int x, int y)
780803
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "get_value", new object[] { 2, 3 }, "override GetValue(int x, int y)")]
781804
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "get_value", new object[] { 2 }, "override get_value(int x)")]
782-
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "get_value_2", new object[] { 2 }, "override GetValue2(int x)")]
783-
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "get_value_3", new object[] { 2 }, "new GetValue3(int x)")]
805+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "get_value", new object[] { }, "get_value()")]
806+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "A", new object[] { }, "A()")]
807+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "a", new object[] { }, "a()")]
808+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "GetValue2", new object[] { 2 }, "override GetValue2(int x)")]
809+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "GetValue3", new object[] { 2 }, "new GetValue3(int x)")]
810+
// original beats fake
811+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "get_value_2", new object[] { 2 }, "get_value_2(int x)")]
812+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "get_value_3", new object[] { 2 }, "get_value_3(int x)")]
813+
814+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "a", new object[] { "AlreadyDefinedSnakeCaseMemberTestBaseClass" }, "a(AlreadyDefinedSnakeCaseMemberTestBaseClass)")]
815+
// A(PyObject) is real
816+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "A", new object[] { "AlreadyDefinedSnakeCaseMemberTestBaseClass" }, "A(PyObject)")]
817+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "a", new object[] { "Type" }, "A(PyObject)")]
818+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "A", new object[] { "Type" }, "A(PyObject)")]
819+
[TestCase(typeof(AlreadyDefinedSnakeCaseMemberTestDerivedClass), "A", new object[] { "Type" }, "A(PyObject)")]
784820
public void BindsSnakeCasedMethodAsOverload(Type type, string methodName, object[] args, string expectedMessage)
785821
{
822+
if (args.Length == 1)
823+
{
824+
if (args[0] is "AlreadyDefinedSnakeCaseMemberTestBaseClass")
825+
{
826+
args = new object[] { new AlreadyDefinedSnakeCaseMemberTestBaseClass() };
827+
}
828+
else if (args[0] is "Type")
829+
{
830+
args = new object[] { typeof(string) };
831+
}
832+
}
833+
786834
var obj = Activator.CreateInstance(type);
787835
using var pyObj = obj.ToPython();
788836

@@ -900,6 +948,60 @@ public void DoesntBindSnakeCasedMemberIfAlreadyOriginallyDefinedAsMethodInBaseAb
900948
Assert.AreEqual(654, method.Invoke().As<int>());
901949
}
902950

951+
public class Class1
952+
{
953+
}
954+
955+
private class TestClass1
956+
{
957+
public dynamic get(Class1 s)
958+
{
959+
return "dynamic get(Class1 s)";
960+
}
961+
}
962+
963+
private class TestClass2 : TestClass1
964+
{
965+
public PyObject Get(PyObject o)
966+
{
967+
return "PyObject Get(PyObject o)".ToPython();
968+
}
969+
970+
public dynamic Get(Type t)
971+
{
972+
return "dynamic Get(Type t)";
973+
}
974+
}
975+
976+
[Test]
977+
public void BindsCorrectOverloadForClassName()
978+
{
979+
using var obj = new TestClass2().ToPython();
980+
981+
var result = obj.GetAttr("get").Invoke(new Class1().ToPython()).As<string>();
982+
Assert.AreEqual("dynamic get(Class1 s)", result);
983+
984+
result = obj.GetAttr("get").Invoke(new TestClass1().ToPython()).As<string>();
985+
Assert.AreEqual("PyObject Get(PyObject o)", result);
986+
987+
using (Py.GIL())
988+
{
989+
// Passing type name directly instead of typeof(Class1) from C#
990+
var module = PyModule.FromString("module", $@"
991+
from clr import AddReference
992+
AddReference(""Python.EmbeddingTest"")
993+
994+
from Python.EmbeddingTest import *
995+
996+
def call(instance):
997+
return instance.get(ClassManagerTests.Class1)
998+
");
999+
1000+
result = module.GetAttr("call").Invoke(obj).As<string>();
1001+
Assert.AreEqual("PyObject Get(PyObject o)", result);
1002+
}
1003+
}
1004+
9031005
#endregion
9041006
}
9051007

0 commit comments

Comments
 (0)