Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/embed_tests/TestMethodBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,23 @@ public string ImplicitConversionSameArgumentCount2(string symbol, decimal quanti

// ----

public string GetValue(string name)
{
return "GetValue(name)";
}

public string GetValue(string name, string defaultValue)
{
return "GetValue(name, defaultValue)";
}

public int GetValue(string name, int defaultValue)
{
return defaultValue;
}

// ----

public string VariableArgumentsMethod(params CSharpModel[] paramsParams)
{
return "VariableArgumentsMethod(CSharpModel[])";
Expand Down Expand Up @@ -895,6 +912,35 @@ def call_method(instance):
Assert.AreEqual(expectedResult, result);
}

[TestCase("GetValue('name', **{})", "GetValue(name)")]
[TestCase("GetValue('name', 'default-value', **{})", "GetValue(name, defaultValue)")]
[TestCase("GetValue('name', defaultValue='default-value', **{})", "GetValue(name, defaultValue)")]
[TestCase("GetValue('name', **{'defaultValue': 'default-value'})", "GetValue(name, defaultValue)")]
[TestCase("Method1('abc', **{})", "Method1 Overload 1")]
public void BindsOverloadedMethodCalledWithEmptyOrUnpackedKwargs(string methodCallCode, string expectedResult)
{
using var _ = Py.GIL();

dynamic module = PyModule.FromString("BindsOverloadedMethodCalledWithEmptyOrUnpackedKwargs", @$"
def call_method(instance):
return instance.{methodCallCode}

def call_method_forwarding_args_and_kwargs(instance):
# Common decorator/monkeypatch idiom: forward *args and **kwargs,
# with kwargs being an empty dict when no keyword arguments are passed
def wrapper(name, *args, **kwargs):
return instance.GetValue(name, *args, **kwargs)
return wrapper('name')
");

var instance = new OverloadsTestClass();
var result = module.call_method(instance).As<string>();
Assert.AreEqual(expectedResult, result);

var forwardedResult = module.call_method_forwarding_args_and_kwargs(instance).As<string>();
Assert.AreEqual("GetValue(name)", forwardedResult);
}

public class CSharpClass
{
public string CalledMethodMessage { get; private set; }
Expand Down
4 changes: 2 additions & 2 deletions src/perf_tests/Python.PerformanceTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.*" />
<PackageReference Include="quantconnect.pythonnet" Version="2.0.59" GeneratePathProperty="true">
<PackageReference Include="quantconnect.pythonnet" Version="2.0.60" GeneratePathProperty="true">
<IncludeAssets>compile</IncludeAssets>
</PackageReference>
</ItemGroup>
Expand All @@ -25,7 +25,7 @@
</Target>

<Target Name="CopyBaseline" AfterTargets="Build">
<Copy SourceFiles="$(NuGetPackageRoot)quantconnect.pythonnet\2.0.59\lib\net10.0\Python.Runtime.dll" DestinationFolder="$(OutDir)baseline" />
<Copy SourceFiles="$(NuGetPackageRoot)quantconnect.pythonnet\2.0.60\lib\net10.0\Python.Runtime.dll" DestinationFolder="$(OutDir)baseline" />
</Target>

<Target Name="CopyNewBuild" AfterTargets="Build">
Expand Down
11 changes: 7 additions & 4 deletions src/runtime/MethodBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,11 +475,14 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe

internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedReference kw, MethodBase info)
{
// If we have KWArgs create dictionary and collect them
// If we have KWArgs create dictionary and collect them.
// An empty kwargs dict (e.g. calling with **{}) is equivalent to no kwargs at all,
// so we only create the dictionary if there are actual keyword arguments,
// else the binding code below would try to index into empty parameter name arrays.
Dictionary<string, PyObject> kwArgDict = null;
if (kw != null)
var pyKwArgsCount = kw == null ? 0 : (int)Runtime.PyDict_Size(kw);
if (pyKwArgsCount > 0)
{
var pyKwArgsCount = (int)Runtime.PyDict_Size(kw);
kwArgDict = new Dictionary<string, PyObject>(pyKwArgsCount);
using var keylist = Runtime.PyDict_Keys(kw);
using var valueList = Runtime.PyDict_Values(kw);
Expand All @@ -490,7 +493,7 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
kwArgDict[keyStr!] = new PyObject(value);
}
}
var hasNamedArgs = kwArgDict != null && kwArgDict.Count > 0;
var hasNamedArgs = kwArgDict != null;

// Fetch our methods we are going to attempt to match and bind too.
var methods = info == null ? GetMethods()
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
[assembly: InternalsVisibleTo("Python.EmbeddingTest, PublicKey=00240000048000009400000006020000002400005253413100040000110000005ffd8f49fb44ab0641b3fd8d55e749f716e6dd901032295db641eb98ee46063cbe0d4a1d121ef0bc2af95f8a7438d7a80a3531316e6b75c2dae92fb05a99f03bf7e0c03980e1c3cfb74ba690aca2f3339ef329313bcc5dccced125a4ffdc4531dcef914602cd5878dc5fbb4d4c73ddfbc133f840231343e013762884d6143189")]
[assembly: InternalsVisibleTo("Python.Test, PublicKey=00240000048000009400000006020000002400005253413100040000110000005ffd8f49fb44ab0641b3fd8d55e749f716e6dd901032295db641eb98ee46063cbe0d4a1d121ef0bc2af95f8a7438d7a80a3531316e6b75c2dae92fb05a99f03bf7e0c03980e1c3cfb74ba690aca2f3339ef329313bcc5dccced125a4ffdc4531dcef914602cd5878dc5fbb4d4c73ddfbc133f840231343e013762884d6143189")]

[assembly: AssemblyVersion("2.0.59")]
[assembly: AssemblyFileVersion("2.0.59")]
[assembly: AssemblyVersion("2.0.60")]
[assembly: AssemblyFileVersion("2.0.60")]
2 changes: 1 addition & 1 deletion src/runtime/Python.Runtime.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<RootNamespace>Python.Runtime</RootNamespace>
<AssemblyName>Python.Runtime</AssemblyName>
<PackageId>QuantConnect.pythonnet</PackageId>
<Version>2.0.59</Version>
<Version>2.0.60</Version>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/pythonnet/pythonnet</RepositoryUrl>
Expand Down
Loading