-
Notifications
You must be signed in to change notification settings - Fork 762
Domain reload test cases fixes #1287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
fc7da1d
72fafdd
20861b2
2253ef3
635edac
0ee931e
3dad96e
90a81f3
10276f1
4d0e2ce
02fa245
91c881c
284e8e1
fe96781
6ff9e0b
4d2d05b
5f061bc
3adc559
e8543cf
61b0d8c
c8bacf3
cde5c23
a956773
ee3b391
9b4d5f9
a2f3294
46dcb9d
10116bb
102054e
329de5d
f97262b
ceb3fab
2d6ae4c
16a39a6
ace340d
78a8088
3232f79
87287a5
44b4800
79516f1
421f665
5e4c976
9d1991a
bcf0cd6
73e5a6b
510a7ae
21eb14c
59e81e2
1383b5a
fbc06ef
b3e86da
0b027c6
b4533c4
0a3f044
639236a
3069285
5c14aad
00c19d5
833e836
62ae107
eedbae5
73f39bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Also add a test
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -771,6 +771,84 @@ def after_reload(): | |
print(bar.__repr__()) | ||
", | ||
}, | ||
|
||
new TestCase | ||
{ | ||
Name = "out_to_ref_param", | ||
DotNetBefore = @" | ||
namespace TestNamespace | ||
{ | ||
|
||
[System.Serializable] | ||
public class Data | ||
{ | ||
public int num = -1; | ||
} | ||
|
||
[System.Serializable] | ||
public class Cls | ||
{ | ||
public static void MyFn (out Data a) | ||
{ | ||
a = new Data(); | ||
a.num = 9001; | ||
} | ||
} | ||
}", | ||
DotNetAfter = @" | ||
namespace TestNamespace | ||
{ | ||
|
||
[System.Serializable] | ||
public class Data | ||
{ | ||
public int num = -1; | ||
} | ||
|
||
[System.Serializable] | ||
public class Cls | ||
{ | ||
public static void MyFn (ref Data a) | ||
{ | ||
a.num = 7; | ||
} | ||
} | ||
}", | ||
PythonCode = @" | ||
import clr | ||
import sys | ||
clr.AddReference('DomainTests') | ||
import TestNamespace | ||
import System | ||
|
||
def before_reload(): | ||
|
||
foo = TestNamespace.Data() | ||
bar = TestNamespace.Cls.MyFn(foo) | ||
assert bar.num == 9001 | ||
# foo shouldn't have changed. | ||
assert foo.num == -1 | ||
|
||
|
||
def after_reload(): | ||
|
||
try: | ||
# Now that the function takes a ref type, we must pass a valid object. | ||
bar = TestNamespace.Cls.MyFn(None) | ||
except System.NullReferenceException as e: | ||
print('caught expected exception') | ||
else: | ||
raise AssertionError('failed to raise') | ||
|
||
foo = TestNamespace.Data() | ||
bar = TestNamespace.Cls.MyFn(foo) | ||
# foo should have changed | ||
assert foo.num == 7 | ||
assert bar.num == 7 | ||
# Pythonnet also returns a new object with `ref`-quialified parameters | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. *qualified |
||
assert foo is not bar | ||
", | ||
}, | ||
}; | ||
|
||
/// <summary> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,50 @@ | ||
using System; | ||
using System.Reflection; | ||
using System.Runtime.Serialization; | ||
using System.Runtime.Serialization.Formatters.Binary; | ||
using System.IO; | ||
using System.Linq; | ||
|
||
namespace Python.Runtime | ||
{ | ||
[Serializable] | ||
internal struct MaybeMethodBase<T> : ISerializable where T: MethodBase | ||
{ | ||
[Serializable] | ||
struct ParameterHelper : IEquatable<ParameterInfo> | ||
{ | ||
public enum TypeModifier | ||
{ | ||
None, | ||
In, | ||
Out, | ||
Ref | ||
} | ||
public readonly string Name; | ||
public readonly TypeModifier Modifier; | ||
|
||
public ParameterHelper(ParameterInfo tp) | ||
{ | ||
Name = tp.ParameterType.AssemblyQualifiedName; | ||
Modifier = TypeModifier.None; | ||
|
||
if (tp.IsIn) | ||
{ | ||
Modifier = TypeModifier.In; | ||
} | ||
else if (tp.IsOut) | ||
{ | ||
Modifier = TypeModifier.Out; | ||
} | ||
Comment on lines
+38
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure these mean what you think they do. See the recent PR #1308 . Can't find corresponding spec, but I suspect for This is also the reason why I suggested to add extra tests later. BTW, this can be fixed in a separate PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't aware of those Attributes. And yes, we'd need to check for ByRef as a parameter with the attribute would be |
||
else if (tp.ParameterType.IsByRef) | ||
{ | ||
Modifier = TypeModifier.Ref; | ||
} | ||
} | ||
|
||
public bool Equals(ParameterInfo other) | ||
{ | ||
return this.Equals(new ParameterHelper(other)); | ||
} | ||
} | ||
public static implicit operator MaybeMethodBase<T> (T ob) => new MaybeMethodBase<T>(ob); | ||
|
||
string name; | ||
|
@@ -64,11 +100,11 @@ internal MaybeMethodBase(SerializationInfo serializationInfo, StreamingContext c | |
var tp = Type.GetType(serializationInfo.GetString("t")); | ||
// Get the method's parameters types | ||
var field_name = serializationInfo.GetString("f"); | ||
var param = (string[])serializationInfo.GetValue("p", typeof(string[])); | ||
var param = (ParameterHelper[])serializationInfo.GetValue("p", typeof(ParameterHelper[])); | ||
Type[] types = new Type[param.Length]; | ||
for (int i = 0; i < param.Length; i++) | ||
{ | ||
types[i] = Type.GetType(param[i]); | ||
types[i] = Type.GetType(param[i].Name); | ||
} | ||
// Try to get the method | ||
MethodBase mb = tp.GetMethod(field_name, ClassManager.BindingFlags, binder:null, types:types, modifiers:null); | ||
|
@@ -81,7 +117,29 @@ internal MaybeMethodBase(SerializationInfo serializationInfo, StreamingContext c | |
// Do like in ClassManager.GetClassInfo | ||
if(mb != null && ClassManager.ShouldBindMethod(mb)) | ||
{ | ||
info = mb; | ||
// One more step: Changing: | ||
// void MyFn (ref int a) | ||
// to: | ||
// void MyFn (out int a) | ||
// will still find the fucntion correctly as, `in`, `out` and `ref` | ||
// are all represented as a reference type. Query the method we got | ||
// and validate the parameters | ||
bool matches = true; | ||
if (param.Length != 0) | ||
{ | ||
foreach (var item in Enumerable.Zip(param, mb.GetParameters(), (x, y) => new {x, y})) | ||
{ | ||
if (!item.x.Equals(item.y)) | ||
{ | ||
matches = false; | ||
break; | ||
} | ||
} | ||
} | ||
if (matches) | ||
{ | ||
info = mb; | ||
} | ||
} | ||
} | ||
catch (Exception e) | ||
|
@@ -97,13 +155,8 @@ public void GetObjectData(SerializationInfo serializationInfo, StreamingContext | |
{ | ||
serializationInfo.AddValue("f", info.Name); | ||
serializationInfo.AddValue("t", info.ReflectedType.AssemblyQualifiedName); | ||
var p = info.GetParameters(); | ||
string[] types = new string[p.Length]; | ||
for (int i = 0; i < p.Length; i++) | ||
{ | ||
types[i] = p[i].ParameterType.AssemblyQualifiedName; | ||
} | ||
serializationInfo.AddValue("p", types, typeof(string[])); | ||
ParameterHelper[] parameters = (from p in info.GetParameters() select new ParameterHelper(p)).ToArray(); | ||
serializationInfo.AddValue("p", parameters, typeof(ParameterHelper[])); | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest to add
ref
toout
andin
toref
test cases as well (in a separate PR; let's not clutter this one).