Skip to content

Commit a685c20

Browse files
authored
Merge pull request #93 from jhonabreul/bug-snake-cased-arguments-constructors
Constructors with arguments snake-cased version
2 parents 8fb227a + c799b7e commit a685c20

File tree

6 files changed

+123
-15
lines changed

6 files changed

+123
-15
lines changed

src/embed_tests/TestMethodBinder.cs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,34 @@ public string ImplicitConversionSameArgumentCount2(string symbol, decimal quanti
805805
{
806806
return "ImplicitConversionSameArgumentCount2 2";
807807
}
808+
809+
// ----
810+
811+
public string VariableArgumentsMethod(params CSharpModel[] paramsParams)
812+
{
813+
return "VariableArgumentsMethod(CSharpModel[])";
814+
}
815+
816+
public string VariableArgumentsMethod(params PyObject[] paramsParams)
817+
{
818+
return "VariableArgumentsMethod(PyObject[])";
819+
}
820+
821+
public string ConstructorMessage { get; set; }
822+
823+
public OverloadsTestClass(params CSharpModel[] paramsParams)
824+
{
825+
ConstructorMessage = "OverloadsTestClass(CSharpModel[])";
826+
}
827+
828+
public OverloadsTestClass(params PyObject[] paramsParams)
829+
{
830+
ConstructorMessage = "OverloadsTestClass(PyObject[])";
831+
}
832+
833+
public OverloadsTestClass()
834+
{
835+
}
808836
}
809837

810838
[TestCase("Method1('abc', namedArg1=10, namedArg2=321)", "Method1 Overload 1")]
@@ -898,6 +926,75 @@ def call_method(instance):
898926
Assert.IsFalse(Exceptions.ErrorOccurred());
899927
}
900928

929+
[Test]
930+
public void BindsConstructorToSnakeCasedArgumentsVersion([Values] bool useCamelCase, [Values] bool passOptionalArgument)
931+
{
932+
using var _ = Py.GIL();
933+
934+
var argument1Name = useCamelCase ? "someArgument" : "some_argument";
935+
var argument2Name = useCamelCase ? "anotherArgument" : "another_argument";
936+
var argument2Code = passOptionalArgument ? $", {argument2Name}=\"another argument value\"" : "";
937+
938+
var module = PyModule.FromString("BindsConstructorToSnakeCasedArgumentsVersion", @$"
939+
from clr import AddReference
940+
AddReference(""System"")
941+
from Python.EmbeddingTest import *
942+
943+
def create_instance():
944+
return TestMethodBinder.CSharpModel({argument1Name}=1{argument2Code})
945+
");
946+
var exception = Assert.Throws<ClrBubbledException>(() => module.GetAttr("create_instance").Invoke());
947+
var sourceException = exception.InnerException;
948+
Assert.IsInstanceOf<NotImplementedException>(sourceException);
949+
950+
var expectedMessage = passOptionalArgument
951+
? "Constructor with arguments: someArgument=1. anotherArgument=\"another argument value\""
952+
: "Constructor with arguments: someArgument=1. anotherArgument=\"another argument default value\"";
953+
Assert.AreEqual(expectedMessage, sourceException.Message);
954+
}
955+
956+
[Test]
957+
public void PyObjectArrayHasPrecedenceOverOtherTypeArrays()
958+
{
959+
using var _ = Py.GIL();
960+
961+
var module = PyModule.FromString("PyObjectArrayHasPrecedenceOverOtherTypeArrays", @$"
962+
from clr import AddReference
963+
AddReference(""System"")
964+
from Python.EmbeddingTest import *
965+
966+
class PythonModel(TestMethodBinder.CSharpModel):
967+
pass
968+
969+
def call_method():
970+
return TestMethodBinder.OverloadsTestClass().VariableArgumentsMethod(PythonModel(), PythonModel())
971+
");
972+
973+
var result = module.GetAttr("call_method").Invoke().As<string>();
974+
Assert.AreEqual("VariableArgumentsMethod(PyObject[])", result);
975+
}
976+
977+
[Test]
978+
public void PyObjectArrayHasPrecedenceOverOtherTypeArraysInConstructors()
979+
{
980+
using var _ = Py.GIL();
981+
982+
var module = PyModule.FromString("PyObjectArrayHasPrecedenceOverOtherTypeArrays", @$"
983+
from clr import AddReference
984+
AddReference(""System"")
985+
from Python.EmbeddingTest import *
986+
987+
class PythonModel(TestMethodBinder.CSharpModel):
988+
pass
989+
990+
def get_instance():
991+
return TestMethodBinder.OverloadsTestClass(PythonModel(), PythonModel())
992+
");
993+
994+
var instance = module.GetAttr("get_instance").Invoke();
995+
Assert.AreEqual("OverloadsTestClass(PyObject[])", instance.GetAttr("ConstructorMessage").As<string>());
996+
}
997+
901998

902999
// Used to test that we match this function with Py DateTime & Date Objects
9031000
public static int GetMonth(DateTime test)
@@ -918,6 +1015,12 @@ public CSharpModel()
9181015
new TestImplicitConversion()
9191016
};
9201017
}
1018+
1019+
public CSharpModel(int someArgument, string anotherArgument = "another argument default value")
1020+
{
1021+
throw new NotImplementedException($"Constructor with arguments: someArgument={someArgument}. anotherArgument=\"{anotherArgument}\"");
1022+
}
1023+
9211024
public void TestList(List<TestImplicitConversion> conversions)
9221025
{
9231026
if (!conversions.Any())

src/perf_tests/Python.PerformanceTests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1414
</PackageReference>
1515
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.*" />
16-
<PackageReference Include="quantconnect.pythonnet" Version="2.0.37" GeneratePathProperty="true">
16+
<PackageReference Include="quantconnect.pythonnet" Version="2.0.38" GeneratePathProperty="true">
1717
<IncludeAssets>compile</IncludeAssets>
1818
</PackageReference>
1919
</ItemGroup>
@@ -25,7 +25,7 @@
2525
</Target>
2626

2727
<Target Name="CopyBaseline" AfterTargets="Build">
28-
<Copy SourceFiles="$(NuGetPackageRoot)quantconnect.pythonnet\2.0.37\lib\net6.0\Python.Runtime.dll" DestinationFolder="$(OutDir)baseline" />
28+
<Copy SourceFiles="$(NuGetPackageRoot)quantconnect.pythonnet\2.0.38\lib\net6.0\Python.Runtime.dll" DestinationFolder="$(OutDir)baseline" />
2929
</Target>
3030

3131
<Target Name="CopyNewBuild" AfterTargets="Build">

src/runtime/ClassManager.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,11 @@ void AddMember(string name, string snakeCasedName, bool isStaticReadonlyCallable
552552
methodList = methods[name] = new ();
553553
}
554554
methodList.Add(ctor, true);
555+
// Same constructor, but with snake-cased arguments
556+
if (ctor.GetParameters().Any(pi => pi.Name?.ToSnakeCase() != pi.Name))
557+
{
558+
methodList.Add(ctor, false);
559+
}
555560
continue;
556561

557562
case MemberTypes.Property:

src/runtime/MethodBinder.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,16 @@ internal static int ArgPrecedence(Type t, MethodInformation mi)
365365
return -1;
366366
}
367367

368+
if (t.IsArray)
369+
{
370+
Type e = t.GetElementType();
371+
if (e == objectType)
372+
{
373+
return 2500;
374+
}
375+
return 100 + ArgPrecedence(e, mi);
376+
}
377+
368378
TypeCode tc = Type.GetTypeCode(t);
369379
// TODO: Clean up
370380
switch (tc)
@@ -406,16 +416,6 @@ internal static int ArgPrecedence(Type t, MethodInformation mi)
406416
return 40;
407417
}
408418

409-
if (t.IsArray)
410-
{
411-
Type e = t.GetElementType();
412-
if (e == objectType)
413-
{
414-
return 2500;
415-
}
416-
return 100 + ArgPrecedence(e, mi);
417-
}
418-
419419
return 2000;
420420
}
421421

src/runtime/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
[assembly: InternalsVisibleTo("Python.EmbeddingTest, PublicKey=00240000048000009400000006020000002400005253413100040000110000005ffd8f49fb44ab0641b3fd8d55e749f716e6dd901032295db641eb98ee46063cbe0d4a1d121ef0bc2af95f8a7438d7a80a3531316e6b75c2dae92fb05a99f03bf7e0c03980e1c3cfb74ba690aca2f3339ef329313bcc5dccced125a4ffdc4531dcef914602cd5878dc5fbb4d4c73ddfbc133f840231343e013762884d6143189")]
55
[assembly: InternalsVisibleTo("Python.Test, PublicKey=00240000048000009400000006020000002400005253413100040000110000005ffd8f49fb44ab0641b3fd8d55e749f716e6dd901032295db641eb98ee46063cbe0d4a1d121ef0bc2af95f8a7438d7a80a3531316e6b75c2dae92fb05a99f03bf7e0c03980e1c3cfb74ba690aca2f3339ef329313bcc5dccced125a4ffdc4531dcef914602cd5878dc5fbb4d4c73ddfbc133f840231343e013762884d6143189")]
66

7-
[assembly: AssemblyVersion("2.0.37")]
8-
[assembly: AssemblyFileVersion("2.0.37")]
7+
[assembly: AssemblyVersion("2.0.38")]
8+
[assembly: AssemblyFileVersion("2.0.38")]

src/runtime/Python.Runtime.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<RootNamespace>Python.Runtime</RootNamespace>
66
<AssemblyName>Python.Runtime</AssemblyName>
77
<PackageId>QuantConnect.pythonnet</PackageId>
8-
<Version>2.0.37</Version>
8+
<Version>2.0.38</Version>
99
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
1010
<PackageLicenseFile>LICENSE</PackageLicenseFile>
1111
<RepositoryUrl>https://github.com/pythonnet/pythonnet</RepositoryUrl>

0 commit comments

Comments
 (0)