◐ Shell
clean mode source ↗

Fix kwarg func resolution by jmlidbetter · Pull Request #1136 · pythonnet/pythonnet

Expand Up @@ -279,6 +279,23 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info) return Bind(inst, args, kw, info, null); }
private readonly struct MatchedMethod { public MatchedMethod(int kwargsMatched, int defaultsNeeded, object[] margs, int outs, MethodBase mb) { KwargsMatched = kwargsMatched; DefaultsNeeded = defaultsNeeded; ManagedArgs = margs; Outs = outs; Method = mb; }
public int KwargsMatched { get; } public int DefaultsNeeded { get; } public object[] ManagedArgs { get; } public int Outs { get; } public MethodBase Method { get; } }
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo) { // loop to find match, return invoker w/ or /wo error Expand Down Expand Up @@ -311,6 +328,8 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth _methods = GetMethods(); }
var argMatchedMethods = new List<MatchedMethod>(_methods.Length);
// TODO: Clean up foreach (MethodBase mi in _methods) { Expand All @@ -321,8 +340,10 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth ParameterInfo[] pi = mi.GetParameters(); ArrayList defaultArgList; bool paramsArray; int kwargsMatched; int defaultsNeeded;
if (!MatchesArgumentCount(pynargs, pi, kwargDict, out paramsArray, out defaultArgList)) if (!MatchesArgumentCount(pynargs, pi, kwargDict, out paramsArray, out defaultArgList, out kwargsMatched, out defaultsNeeded)) { continue; } Expand All @@ -336,6 +357,47 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth continue; }
var matchedMethod = new MatchedMethod(kwargsMatched, defaultsNeeded, margs, outs, mi); argMatchedMethods.Add(matchedMethod); } if (argMatchedMethods.Count > 0) { var bestKwargMatchCount = argMatchedMethods.Max(x => x.KwargsMatched); var fewestDefaultsRequired = argMatchedMethods.Where(x => x.KwargsMatched == bestKwargMatchCount).Min(x => x.DefaultsNeeded);
int bestCount = 0; int bestMatchIndex = -1;
for (int index = 0; index < argMatchedMethods.Count; index++) { var testMatch = argMatchedMethods[index]; if (testMatch.DefaultsNeeded == fewestDefaultsRequired && testMatch.KwargsMatched == bestKwargMatchCount) { bestCount++; if (bestMatchIndex == -1) bestMatchIndex = index; } }
if (bestCount > 1 && fewestDefaultsRequired > 0) { // Best effort for determining method to match on gives multiple possible // matches and we need at least one default argument - bail from this point return null; }
// If we're here either: // (a) There is only one best match // (b) There are multiple best matches but none of them require // default arguments // in the case of (a) we're done by default. For (b) regardless of which // method we choose, all arguments are specified _and_ can be converted // from python to C# so picking any will suffice MatchedMethod bestMatch = argMatchedMethods[bestMatchIndex]; var margs = bestMatch.ManagedArgs; var outs = bestMatch.Outs; var mi = bestMatch.Method;
object target = null; if (!mi.IsStatic && inst != IntPtr.Zero) { Expand Down Expand Up @@ -575,11 +637,16 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] parameters, Dictionary<string, IntPtr> kwargDict, out bool paramsArray, out ArrayList defaultArgList) out ArrayList defaultArgList, out int kwargsMatched, out int defaultsNeeded) { defaultArgList = null; var match = false; paramsArray = parameters.Length > 0 ? Attribute.IsDefined(parameters[parameters.Length - 1], typeof(ParamArrayAttribute)) : false; var kwargCount = kwargDict.Count; kwargsMatched = 0; defaultsNeeded = 0;
if (positionalArgumentCount == parameters.Length && kwargDict.Count == 0) { Expand All @@ -599,6 +666,7 @@ static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] pa // no need to check for a default parameter, but put a null // placeholder in defaultArgList defaultArgList.Add(null); kwargsMatched++; } else if (parameters[v].IsOptional) { Expand All @@ -607,6 +675,7 @@ static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] pa // The GetDefaultValue() extension method will return the value // to be passed in as the parameter value defaultArgList.Add(parameters[v].GetDefaultValue()); defaultsNeeded++; } else if(!paramsArray) { Expand Down