Skip to content

Commit f59335f

Browse files
committed
Post rebase fix
1 parent d87584b commit f59335f

File tree

1 file changed

+67
-158
lines changed

1 file changed

+67
-158
lines changed

src/runtime/methodbinder.cs

+67-158
Original file line numberDiff line numberDiff line change
@@ -396,164 +396,73 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
396396
}
397397

398398

399-
for (int index = 0; index < argMatchedMethods.Count; index++)
400-
{
401-
var testMatch = argMatchedMethods[index];
402-
if (testMatch.DefaultsNeeded == fewestDefaultsRequired && testMatch.KwargsMatched == bestKwargMatchCount)
403-
{
404-
bestCount++;
405-
if (bestMatchIndex == -1)
406-
bestMatchIndex = index;
407-
}
408-
}
409-
410-
if (bestCount > 1 && fewestDefaultsRequired > 0)
411-
{
412-
// Best effort for determining method to match on gives multiple possible
413-
// matches and we need at least one default argument - bail from this point
414-
StringBuilder stringBuilder = new StringBuilder("Not enough arguments provided to disambiguate the method. Found:");
415-
foreach (var matchedMethod in argMatchedMethods)
416-
{
417-
stringBuilder.AppendLine();
418-
stringBuilder.Append(matchedMethod.Method.ToString());
419-
}
420-
Exceptions.SetError(Exceptions.TypeError, stringBuilder.ToString());
421-
return null;
422-
}
423-
424-
// If we're here either:
425-
// (a) There is only one best match
426-
// (b) There are multiple best matches but none of them require
427-
// default arguments
428-
// in the case of (a) we're done by default. For (b) regardless of which
429-
// method we choose, all arguments are specified _and_ can be converted
430-
// from python to C# so picking any will suffice
431-
MatchedMethod bestMatch = argMatchedMethods[bestMatchIndex];
432-
var margs = bestMatch.ManagedArgs;
433-
var outs = bestMatch.Outs;
434-
var mi = bestMatch.Method;
435-
436-
object target = null;
437-
if (!mi.IsStatic && inst != IntPtr.Zero)
438-
{
439-
//CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
440-
// InvalidCastException: Unable to cast object of type
441-
// 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject'
442-
var co = ManagedType.GetManagedObject(inst) as CLRObject;
443-
444-
// Sanity check: this ensures a graceful exit if someone does
445-
// something intentionally wrong like call a non-static method
446-
// on the class rather than on an instance of the class.
447-
// XXX maybe better to do this before all the other rigmarole.
448-
if (co == null)
449-
{
450-
Exceptions.SetError(Exceptions.TypeError, "Invoked a non-static method with an invalid instance");
451-
return null;
452-
}
453-
target = co.inst;
454-
}
455-
456-
return new Binding(mi, target, margs, outs);
457-
}
458-
else if (isGeneric && info == null && methodinfo != null)
459-
{
460-
// We weren't able to find a matching method but at least one
461-
// is a generic method and info is null. That happens when a generic
462-
// method was not called using the [] syntax. Let's introspect the
463-
// type of the arguments and use it to construct the correct method.
464-
Type[] types = Runtime.PythonArgsToTypeArray(args, true);
465-
MethodInfo mi = MatchParameters(methodinfo, types);
466-
if (mi != null)
467-
{
468-
return Bind(inst, args, kw, mi, null);
469-
}
470-
}
471-
if (mismatchedMethods.Count > 0)
472-
{
473-
var aggregateException = GetAggregateException(mismatchedMethods);
474-
Exceptions.SetError(aggregateException);
475-
}
476-
return null;
477-
}
478-
479-
static AggregateException GetAggregateException(IEnumerable<MismatchedMethod> mismatchedMethods)
480-
{
481-
return new AggregateException(mismatchedMethods.Select(m => new ArgumentException($"{m.Exception.Message} in method {m.Method}", m.Exception)));
482-
}
483-
484-
static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference)
485-
{
486-
isNewReference = false;
487-
IntPtr op;
488-
// for a params method, we may have a sequence or single/multiple items
489-
// here we look to see if the item at the paramIndex is there or not
490-
// and then if it is a sequence itself.
491-
if ((pyArgCount - arrayStart) == 1)
492-
{
493-
// we only have one argument left, so we need to check it
494-
// to see if it is a sequence or a single item
495-
IntPtr item = Runtime.PyTuple_GetItem(args, arrayStart);
496-
if (!Runtime.PyString_Check(item) && Runtime.PySequence_Check(item))
497-
{
498-
// it's a sequence (and not a string), so we use it as the op
499-
op = item;
500-
}
501-
else
502-
{
503-
isNewReference = true;
504-
op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
505-
}
506-
}
507-
else
508-
{
509-
isNewReference = true;
510-
op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
511-
}
512-
return op;
513-
}
514-
515-
/// <summary>
516-
/// Attempts to convert Python positional argument tuple and keyword argument table
517-
/// into an array of managed objects, that can be passed to a method.
518-
/// If unsuccessful, returns null and may set a Python error.
519-
/// </summary>
520-
/// <param name="pi">Information about expected parameters</param>
521-
/// <param name="paramsArray"><c>true</c>, if the last parameter is a params array.</param>
522-
/// <param name="args">A pointer to the Python argument tuple</param>
523-
/// <param name="pyArgCount">Number of arguments, passed by Python</param>
524-
/// <param name="kwargDict">Dictionary of keyword argument name to python object pointer</param>
525-
/// <param name="defaultArgList">A list of default values for omitted parameters</param>
526-
/// <param name="needsResolution"><c>true</c>, if overloading resolution is required</param>
527-
/// <param name="outs">Returns number of output parameters</param>
528-
/// <returns>If successful, an array of .NET arguments that can be passed to the method. Otherwise null.</returns>
529-
static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
530-
IntPtr args, int pyArgCount,
531-
Dictionary<string, IntPtr> kwargDict,
532-
ArrayList defaultArgList,
533-
bool needsResolution,
534-
out int outs,
535-
out bool usedImplicitConversion)
536-
{
537-
usedImplicitConversion = false;
538-
outs = 0;
539-
var margs = new object[pi.Length];
540-
int arrayStart = paramsArray ? pi.Length - 1 : -1;
541-
542-
for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++)
543-
{
544-
var parameter = pi[paramIndex];
545-
bool hasNamedParam = kwargDict.ContainsKey(parameter.Name);
546-
bool isNewReference = false;
547-
548-
if (paramIndex >= pyArgCount && !(hasNamedParam || (paramsArray && paramIndex == arrayStart)))
549-
{
550-
if (defaultArgList != null)
551-
{
552-
margs[paramIndex] = defaultArgList[paramIndex - pyArgCount];
553-
}
554-
555-
continue;
556-
}
399+
if (clrtype != null)
400+
{
401+
var typematch = false;
402+
if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype))
403+
{
404+
IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType);
405+
pyoptype = Runtime.PyObject_Type(op);
406+
Exceptions.Clear();
407+
if (pyoptype != IntPtr.Zero)
408+
{
409+
if (pytype != pyoptype)
410+
{
411+
typematch = false;
412+
}
413+
else
414+
{
415+
typematch = true;
416+
clrtype = pi[n].ParameterType;
417+
}
418+
}
419+
if (!typematch)
420+
{
421+
// this takes care of nullables
422+
var underlyingType = Nullable.GetUnderlyingType(pi[n].ParameterType);
423+
if (underlyingType == null)
424+
{
425+
underlyingType = pi[n].ParameterType;
426+
}
427+
// this takes care of enum values
428+
TypeCode argtypecode = Type.GetTypeCode(underlyingType);
429+
TypeCode paramtypecode = Type.GetTypeCode(clrtype);
430+
if (argtypecode == paramtypecode)
431+
{
432+
typematch = true;
433+
clrtype = pi[n].ParameterType;
434+
}
435+
// accepts non-decimal numbers in decimal parameters
436+
if (underlyingType == typeof(decimal))
437+
{
438+
clrtype = pi[n].ParameterType;
439+
typematch = Converter.ToManaged(op, clrtype, out arg, false);
440+
}
441+
// this takes care of implicit conversions
442+
var opImplicit = pi[n].ParameterType.GetMethod("op_Implicit", new[] { clrtype });
443+
if (opImplicit != null)
444+
{
445+
usedImplicitConversion = typematch = opImplicit.ReturnType == pi[n].ParameterType;
446+
clrtype = pi[n].ParameterType;
447+
}
448+
}
449+
Runtime.XDecref(pyoptype);
450+
if (!typematch)
451+
{
452+
margs = null;
453+
break;
454+
}
455+
}
456+
else
457+
{
458+
typematch = true;
459+
clrtype = pi[n].ParameterType;
460+
}
461+
}
462+
else
463+
{
464+
clrtype = pi[n].ParameterType;
465+
}
557466

558467
if (pi[n].IsOut || clrtype.IsByRef)
559468
{

0 commit comments

Comments
 (0)