Skip to content

Commit fe99052

Browse files
Pep8 named arguments generic methods (#86)
- Fix for pep8 named argument support for generic methods. Adding tests reproducing issue
1 parent a6ad62f commit fe99052

File tree

3 files changed

+72
-27
lines changed

3 files changed

+72
-27
lines changed

src/embed_tests/ClassManagerTests.cs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,50 @@ public string JoinToString(string thisIsAStringParameter,
159159
};
160160

161161
private static void Throw() => throw new Exception("Pepe");
162+
163+
public static string GenericMethodBindingStatic<T>(int arg1, SnakeCaseEnum enumValue)
164+
{
165+
return "GenericMethodBindingStatic";
166+
}
167+
168+
public string GenericMethodBinding<T>(int arg1, SnakeCaseEnum enumValue = SnakeCaseEnum.EnumValue3)
169+
{
170+
return "GenericMethodBinding" + arg1;
171+
}
172+
}
173+
174+
[TestCase("generic_method_binding_static", "GenericMethodBindingStatic")]
175+
[TestCase("generic_method_binding", "GenericMethodBinding1")]
176+
[TestCase("generic_method_binding2", "GenericMethodBinding2")]
177+
[TestCase("generic_method_binding3", "GenericMethodBinding3")]
178+
public void GenericMethodBinding(string targetMethod, string expectedReturn)
179+
{
180+
using (Py.GIL())
181+
{
182+
var module = PyModule.FromString("module", $@"
183+
from clr import AddReference
184+
AddReference(""Python.EmbeddingTest"")
185+
186+
from Python.EmbeddingTest import *
187+
188+
def generic_method_binding_static(value):
189+
return ClassManagerTests.SnakeCaseNamesTesClass.generic_method_binding_static[bool](1, enum_value=ClassManagerTests.SnakeCaseEnum.EnumValue1)
190+
191+
def generic_method_binding(value):
192+
return value.generic_method_binding[bool](1, enum_value=ClassManagerTests.SnakeCaseEnum.EnumValue1)
193+
194+
def generic_method_binding2(value):
195+
return value.generic_method_binding[bool](2, ClassManagerTests.SnakeCaseEnum.EnumValue1)
196+
197+
def generic_method_binding3(value):
198+
return value.generic_method_binding[bool](3)
199+
");
200+
201+
using var obj = new SnakeCaseNamesTesClass().ToPython();
202+
var result = module.InvokeMethod(targetMethod, new[] { obj }).As<string>();
203+
204+
Assert.AreEqual(expectedReturn, result);
205+
}
162206
}
163207

164208
[TestCase("StaticReadonlyActionProperty", "static_readonly_action_property", new object[] { })]
@@ -618,13 +662,13 @@ def SetEnumValue3(obj):
618662
obj.EnumValue = ClassManagerTests.SnakeCaseEnum.EnumValue3
619663
620664
def SetEnumValue1SnakeCase(obj):
621-
obj.enum_value = ClassManagerTests.SnakeCaseEnum.ENUM_VALUE1
665+
obj.enum_value = ClassManagerTests.SnakeCaseEnum.ENUM_VALUE_1
622666
623667
def SetEnumValue2SnakeCase(obj):
624-
obj.enum_value = ClassManagerTests.SnakeCaseEnum.ENUM_VALUE2
668+
obj.enum_value = ClassManagerTests.SnakeCaseEnum.ENUM_VALUE_2
625669
626670
def SetEnumValue3SnakeCase(obj):
627-
obj.enum_value = ClassManagerTests.SnakeCaseEnum.ENUM_VALUE3
671+
obj.enum_value = ClassManagerTests.SnakeCaseEnum.ENUM_VALUE_3
628672
");
629673

630674
using var obj = new SnakeCaseNamesTesClass().ToPython();

src/runtime/MethodBinder.cs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal class MethodBinder
2323
public const bool DefaultAllowThreads = true;
2424
public bool allow_threads = DefaultAllowThreads;
2525
public bool init = false;
26+
public bool isOriginal;
2627

2728
internal MethodBinder()
2829
{
@@ -40,15 +41,10 @@ public int Count
4041
}
4142

4243
internal void AddMethod(MethodBase m)
43-
{
44-
AddMethod(m, true);
45-
}
46-
47-
internal void AddMethod(MethodBase m, bool isOriginal)
4844
{
4945
// we added a new method so we have to re sort the method list
5046
init = false;
51-
list.Add(new MethodInformation(m, m.GetParameters(), isOriginal));
47+
list.Add(new MethodInformation(m, m.GetParameters()));
5248
}
5349

5450
/// <summary>
@@ -454,7 +450,7 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
454450
var mi = methodInformation.MethodBase;
455451
var pi = methodInformation.ParameterInfo;
456452
// Avoid accessing the parameter names property unless necessary
457-
var paramNames = hasNamedArgs ? methodInformation.ParameterNames : Array.Empty<string>();
453+
var paramNames = hasNamedArgs ? methodInformation.ParameterNames(isOriginal) : Array.Empty<string>();
458454
int pyArgCount = (int)Runtime.PyTuple_Size(args);
459455

460456
// Special case for operators
@@ -987,30 +983,32 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
987983
[Serializable]
988984
internal class MethodInformation
989985
{
990-
private Lazy<string[]> _parametersNames;
986+
private string[] _parametersNames = null;
991987

992988
public MethodBase MethodBase { get; }
993989

994990
public ParameterInfo[] ParameterInfo { get; }
995991

996-
public bool IsOriginal { get; }
997-
998-
public string[] ParameterNames { get { return _parametersNames.Value; } }
999-
1000-
public MethodInformation(MethodBase methodBase, ParameterInfo[] parameterInfo)
1001-
: this(methodBase, parameterInfo, true)
992+
public string[] ParameterNames(bool isOriginal)
1002993
{
994+
if (_parametersNames == null)
995+
{
996+
if (isOriginal)
997+
{
998+
_parametersNames = ParameterInfo.Select(pi => pi.Name).ToArray();
999+
}
1000+
else
1001+
{
1002+
_parametersNames = ParameterInfo.Select(pi => pi.Name.ToSnakeCase()).ToArray();
1003+
}
1004+
}
1005+
return _parametersNames;
10031006
}
10041007

1005-
public MethodInformation(MethodBase methodBase, ParameterInfo[] parameterInfo, bool isOriginal)
1008+
public MethodInformation(MethodBase methodBase, ParameterInfo[] parameterInfo)
10061009
{
10071010
MethodBase = methodBase;
10081011
ParameterInfo = parameterInfo;
1009-
IsOriginal = isOriginal;
1010-
1011-
_parametersNames = new Lazy<string[]>(() => IsOriginal
1012-
? ParameterInfo.Select(pi => pi.Name).ToArray()
1013-
: ParameterInfo.Select(pi => pi.Name.ToSnakeCase()).ToArray());
10141012
}
10151013

10161014
public override string ToString()

src/runtime/Types/MethodObject.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,26 @@ public MethodObject(MaybeType type, string name, MethodBase[] info, bool allow_t
3434
this.type = type;
3535
this.name = name;
3636
this.infoList = new List<MaybeMethodInfo>();
37-
binder = new MethodBinder();
37+
binder = new MethodBinder
38+
{
39+
isOriginal = isOriginal,
40+
allow_threads = allow_threads
41+
};
3842
foreach (MethodBase item in info)
3943
{
4044
this.infoList.Add(item);
41-
binder.AddMethod(item, isOriginal);
45+
binder.AddMethod(item);
4246
if (item.IsStatic)
4347
{
4448
this.is_static = true;
4549
}
4650
}
47-
binder.allow_threads = allow_threads;
4851
}
4952

5053
public bool IsInstanceConstructor => name == "__init__";
5154

5255
public MethodObject WithOverloads(MethodBase[] overloads)
53-
=> new(type, name, overloads, allow_threads: binder.allow_threads);
56+
=> new(type, name, overloads, allow_threads: binder.allow_threads, isOriginal: binder.isOriginal);
5457

5558
internal MethodBase[] info
5659
{

0 commit comments

Comments
 (0)