Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit49a230b

Browse files
authored
Fix params argument handling (#1106)
Add a check to see if the last parameter is a params parameter. Set the correct flag to show that it is a paramsArray function.Fixes#943 and#331.
1 parent4a92d80 commit49a230b

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed

‎CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
3939
together with Nuitka
4040
- Fixes bug where delegates get casts (dotnetcore)
4141
- Determine size of interpreter longs at runtime
42-
- Handling exceptions ocurred in ModuleObject's getattribute
42+
- Handling exceptions ocurred in ModuleObject's getattribute
4343
- Fill`__classcell__` correctly for Python subclasses of .NET types
44+
- Fixed issue with params methods that are not passed an array.
4445

4546
##[2.4.0][]
4647

‎src/runtime/methodbinder.cs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,41 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
369369
returnnull;
370370
}
371371

372+
staticIntPtrHandleParamsArray(IntPtrargs,intarrayStart,intpyArgCount,outboolisNewReference)
373+
{
374+
isNewReference=false;
375+
IntPtrop;
376+
// for a params method, we may have a sequence or single/multiple items
377+
// here we look to see if the item at the paramIndex is there or not
378+
// and then if it is a sequence itself.
379+
if((pyArgCount-arrayStart)==1)
380+
{
381+
// we only have one argument left, so we need to check it
382+
// to see if it is a sequence or a single item
383+
IntPtritem=Runtime.PyTuple_GetItem(args,arrayStart);
384+
if(!Runtime.PyString_Check(item)&&Runtime.PySequence_Check(item))
385+
{
386+
// it's a sequence (and not a string), so we use it as the op
387+
op=item;
388+
}
389+
else
390+
{
391+
isNewReference=true;
392+
op=Runtime.PyTuple_GetSlice(args,arrayStart,pyArgCount);
393+
if(item!=IntPtr.Zero)
394+
{
395+
Runtime.XDecref(item);
396+
}
397+
}
398+
}
399+
else
400+
{
401+
isNewReference=true;
402+
op=Runtime.PyTuple_GetSlice(args,arrayStart,pyArgCount);
403+
}
404+
returnop;
405+
}
406+
372407
/// <summary>
373408
/// Attempts to convert Python positional argument tuple and keyword argument table
374409
/// into an array of managed objects, that can be passed to a method.
@@ -397,8 +432,9 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
397432
{
398433
varparameter=pi[paramIndex];
399434
boolhasNamedParam=kwargDict.ContainsKey(parameter.Name);
435+
boolisNewReference=false;
400436

401-
if(paramIndex>=pyArgCount&&!hasNamedParam)
437+
if(paramIndex>=pyArgCount&&!(hasNamedParam||(paramsArray&&paramIndex==arrayStart)))
402438
{
403439
if(defaultArgList!=null)
404440
{
@@ -415,11 +451,14 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
415451
}
416452
else
417453
{
418-
op=(arrayStart==paramIndex)
419-
// map remaining Python arguments to a tuple since
420-
// the managed function accepts it - hopefully :]
421-
?Runtime.PyTuple_GetSlice(args,arrayStart,pyArgCount)
422-
:Runtime.PyTuple_GetItem(args,paramIndex);
454+
if(arrayStart==paramIndex)
455+
{
456+
op=HandleParamsArray(args,arrayStart,pyArgCount,outisNewReference);
457+
}
458+
else
459+
{
460+
op=Runtime.PyTuple_GetItem(args,paramIndex);
461+
}
423462
}
424463

425464
boolisOut;
@@ -428,7 +467,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
428467
returnnull;
429468
}
430469

431-
if(arrayStart==paramIndex)
470+
if(isNewReference)
432471
{
433472
// TODO: is this a bug? Should this happen even if the conversion fails?
434473
// GetSlice() creates a new reference but GetItem()
@@ -543,7 +582,7 @@ static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] pa
543582
{
544583
defaultArgList=null;
545584
varmatch=false;
546-
paramsArray=false;
585+
paramsArray=parameters.Length>0?Attribute.IsDefined(parameters[parameters.Length-1],typeof(ParamArrayAttribute)):false;
547586

548587
if(positionalArgumentCount==parameters.Length)
549588
{
@@ -572,7 +611,7 @@ static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] pa
572611
// to be passed in as the parameter value
573612
defaultArgList.Add(parameters[v].GetDefaultValue());
574613
}
575-
else
614+
elseif(!paramsArray)
576615
{
577616
match=false;
578617
}

‎src/tests/test_method.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,37 @@ def test_non_params_array_in_last_place():
257257
result=MethodTest.TestNonParamsArrayInLastPlace(1,2,3)
258258
assertresult
259259

260+
deftest_params_methods_with_no_params():
261+
"""Tests that passing no arguments to a params method
262+
passes an empty array"""
263+
result=MethodTest.TestValueParamsArg()
264+
assertlen(result)==0
265+
266+
result=MethodTest.TestOneArgWithParams('Some String')
267+
assertlen(result)==0
268+
269+
result=MethodTest.TestTwoArgWithParams('Some String','Some Other String')
270+
assertlen(result)==0
271+
272+
deftest_params_methods_with_non_lists():
273+
"""Tests that passing single parameters to a params
274+
method will convert into an array on the .NET side"""
275+
result=MethodTest.TestOneArgWithParams('Some String', [1,2,3,4])
276+
assertlen(result)==4
277+
278+
result=MethodTest.TestOneArgWithParams('Some String',1,2,3,4)
279+
assertlen(result)==4
280+
281+
result=MethodTest.TestOneArgWithParams('Some String', [5])
282+
assertlen(result)==1
283+
284+
result=MethodTest.TestOneArgWithParams('Some String',5)
285+
assertlen(result)==1
286+
287+
deftest_params_method_with_lists():
288+
"""Tests passing multiple lists to a params object[] method"""
289+
result=MethodTest.TestObjectParamsArg([],[])
290+
assertlen(result)==2
260291

261292
deftest_string_out_params():
262293
"""Test use of string out-parameters."""

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp