Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
062a0bc
Reflect PR #1 Support for Decimal
C-SELLERS Feb 3, 2021
5ed5a96
Reflect PR#8 MISSING CONVERTER.CS L516-528 Changes
C-SELLERS Feb 3, 2021
9b5445e
Reflect PR #14
C-SELLERS Feb 4, 2021
709643a
Reflect PR #15
C-SELLERS Feb 4, 2021
a481700
Reflect PR #19
C-SELLERS Feb 4, 2021
de0328c
Reflect PR #25
C-SELLERS Feb 4, 2021
481f4d0
Reflect PR #34
C-SELLERS Feb 4, 2021
863530d
Reflect PR #35
C-SELLERS Feb 4, 2021
5839d21
Implement List Conversion, Reflect PR #37 Tests
C-SELLERS Feb 4, 2021
c362816
Reflect PR #38 Partial: Assembly Manager Improvements
C-SELLERS Feb 4, 2021
cde9b51
Reflect PR #38
C-SELLERS Feb 4, 2021
101624e
Reflect PR #42 KeyValuePairEnumerableObject
C-SELLERS Feb 4, 2021
56a4bcf
Reflect PR #10 Runtime DecimalType
C-SELLERS Feb 4, 2021
508db2e
Add TimeDelta and DateTime tests
C-SELLERS Feb 5, 2021
ebbafad
Fix DecimalConversion test for float conversion
C-SELLERS Feb 5, 2021
53375ce
Converter mod tweaks
C-SELLERS Feb 6, 2021
c8fdbcb
Adjust a few broken PyTests
C-SELLERS Feb 6, 2021
af30873
Use _pydecimal to not interfere with Lean/decimal.py
C-SELLERS Feb 9, 2021
bf1755d
Add MethodBinder tests
C-SELLERS Feb 9, 2021
58d5df0
MethodBinder implicit resolution
Martin-Molinero Feb 4, 2021
0c94228
Fix bad cherry pick
C-SELLERS Feb 10, 2021
44e089a
Refactoring precedence resolution
Martin-Molinero Feb 5, 2021
108eacf
Deal with operator binding
C-SELLERS Feb 10, 2021
6379568
Fix `TestNoOverloadException` unit test
C-SELLERS Feb 10, 2021
9f2796a
Fix for DomainReload tests
C-SELLERS Feb 10, 2021
b0aca5c
Add InEquality Operator Test
C-SELLERS Feb 11, 2021
0f5f0ba
Dont PyObjects precedence in Operator methods
C-SELLERS Feb 11, 2021
ed6ab18
Revert "Merge pull request #1240 from danabr/auto-cast-ret-val-to-int…
C-SELLERS Feb 12, 2021
d87584b
Fix Primitive Conversion to Int
C-SELLERS Feb 15, 2021
f59335f
Post rebase fix
C-SELLERS Feb 15, 2021
bd94e49
Add PrimitiveIntConversion test
C-SELLERS Feb 16, 2021
cd06d10
Add test for interface derived classes
C-SELLERS Feb 16, 2021
aeb20c0
Add to Authors.md
C-SELLERS Feb 16, 2021
ae34f30
Load in current directory into Python Path
C-SELLERS Feb 18, 2021
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
Prev Previous commit
Next Next commit
Revert "Merge pull request #1240 from danabr/auto-cast-ret-val-to-int…
…erface"

This reverts commit 50d947f, reversing
changes made to d44f1da.
  • Loading branch information
C-SELLERS committed Feb 15, 2021
commit ed6ab18ca04337db37f61ba8efaf910b01a468f1
5 changes: 0 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
details about the cause of the failure
- `clr.AddReference` no longer adds ".dll" implicitly
- `PyIter(PyObject)` constructor replaced with static `PyIter.GetIter(PyObject)` method
- BREAKING: Return values from .NET methods that return an interface are now automatically
wrapped in that interface. This is a breaking change for users that rely on being
able to access members that are part of the implementation class, but not the
interface. Use the new __implementation__ or __raw_implementation__ properties to
if you need to "downcast" to the implementation class.
- BREAKING: Parameters marked with `ParameterAttributes.Out` are no longer returned in addition
to the regular method return value (unless they are passed with `ref` or `out` keyword).
- BREAKING: Drop support for the long-deprecated CLR.* prefix.
Expand Down
7 changes: 1 addition & 6 deletions src/runtime/arrayobject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,8 @@ static NewReference NewInstance(Type elementType, BorrowedReference arrayPyType,
public new static IntPtr mp_subscript(IntPtr ob, IntPtr idx)
{
var obj = (CLRObject)GetManagedObject(ob);
var arrObj = (ArrayObject)GetManagedObjectType(ob);
if (!arrObj.type.Valid)
{
return Exceptions.RaiseTypeError(arrObj.type.DeletedMessage);
}
var items = obj.inst as Array;
Type itemType = arrObj.type.Value.GetElementType();
Type itemType = obj.inst.GetType().GetElementType();
int rank = items.Rank;
int index;
object value;
Expand Down
15 changes: 0 additions & 15 deletions src/runtime/converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,6 @@ internal static IntPtr ToPython(object value, Type type)
}
}

if (type.IsInterface)
{
var ifaceObj = (InterfaceObject)ClassManager.GetClass(type);
return ifaceObj.WrapObject(value);
}

// We need to special case interface array handling to ensure we
// produce the correct type. Value may be an array of some concrete
// type (FooImpl[]), but we want access to go via the interface type
// (IFoo[]).
if (type.IsArray && type.GetElementType().IsInterface)
{
return CLRObject.GetInstHandle(value, type);
}

// it the type is a python subclass of a managed type then return the
// underlying python object rather than construct a new wrapper object.
var pyderived = value as IPythonDerivedType;
Expand Down
38 changes: 1 addition & 37 deletions src/runtime/interfaceobject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,43 +76,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
return IntPtr.Zero;
}

return self.WrapObject(obj);
}

/// <summary>
/// Wrap the given object in an interface object, so that only methods
/// of the interface are available.
/// </summary>
public IntPtr WrapObject(object impl)
{
var objPtr = CLRObject.GetInstHandle(impl, pyHandle);
return objPtr;
}

/// <summary>
/// Expose the wrapped implementation through attributes in both
/// converted/encoded (__implementation__) and raw (__raw_implementation__) form.
/// </summary>
public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
{
var clrObj = (CLRObject)GetManagedObject(ob);

if (!Runtime.PyString_Check(key))
{
return Exceptions.RaiseTypeError("string expected");
}

string name = Runtime.GetManagedString(key);
if (name == "__implementation__")
{
return Converter.ToPython(clrObj.inst);
}
else if (name == "__raw_implementation__")
{
return CLRObject.GetInstHandle(clrObj.inst);
}

return Runtime.PyObject_GenericGetAttr(ob, key);
return CLRObject.GetInstHandle(obj, self.pyHandle);
}
}
}
19 changes: 0 additions & 19 deletions src/runtime/managedtype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,25 +109,6 @@ internal static ManagedType GetManagedObject(IntPtr ob)
return null;
}

/// <summary>
/// Given a Python object, return the associated managed object type or null.
/// </summary>
internal static ManagedType GetManagedObjectType(IntPtr ob)
{
if (ob != IntPtr.Zero)
{
IntPtr tp = Runtime.PyObject_TYPE(ob);
var flags = Util.ReadCLong(tp, TypeOffset.tp_flags);
if ((flags & TypeFlags.Managed) != 0)
{
tp = Marshal.ReadIntPtr(tp, TypeOffset.magic());
var gc = (GCHandle)tp;
return (ManagedType)gc.Target;
}
}
return null;
}


internal static ManagedType GetManagedObjectErr(IntPtr ob)
{
Expand Down
6 changes: 4 additions & 2 deletions src/runtime/typemanager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,10 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
InitializeSlot(type, TypeOffset.mp_length, mp_length_slot.Method, slotsHolder);
}

if (!typeof(IEnumerable).IsAssignableFrom(clrType) &&
!typeof(IEnumerator).IsAssignableFrom(clrType))
// we want to do this after the slot stuff above in case the class itself implements a slot method
InitializeSlots(type, impl.GetType());

if (!clrType.GetInterfaces().Any(ifc => ifc == typeof(IEnumerable) || ifc == typeof(IEnumerator)))
{
// The tp_iter slot should only be set for enumerable types.
Marshal.WriteIntPtr(type, TypeOffset.tp_iter, IntPtr.Zero);
Expand Down
22 changes: 1 addition & 21 deletions src/testing/interfacetest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal interface IInternalInterface
{
}


public interface ISayHello1
{
string SayHello();
Expand Down Expand Up @@ -42,27 +43,6 @@ string ISayHello2.SayHello()
return "hello 2";
}

public ISayHello1 GetISayHello1()
{
return this;
}

public void GetISayHello2(out ISayHello2 hello2)
{
hello2 = this;
}

public ISayHello1 GetNoSayHello(out ISayHello2 hello2)
{
hello2 = null;
return null;
}

public ISayHello1 [] GetISayHello1Array()
{
return new[] { this };
}

public interface IPublic
{
}
Expand Down
17 changes: 3 additions & 14 deletions src/testing/subclasstest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,24 +89,13 @@ public static string test_bar(IInterfaceTest x, string s, int i)
}

// test instances can be constructed in managed code
public static SubClassTest create_instance(Type t)
{
return (SubClassTest)t.GetConstructor(new Type[] { }).Invoke(new object[] { });
}

public static IInterfaceTest create_instance_interface(Type t)
public static IInterfaceTest create_instance(Type t)
{
return (IInterfaceTest)t.GetConstructor(new Type[] { }).Invoke(new object[] { });
}

// test instances pass through managed code unchanged ...
public static SubClassTest pass_through(SubClassTest s)
{
return s;
}

// ... but the return type is an interface type, objects get wrapped
public static IInterfaceTest pass_through_interface(IInterfaceTest s)
// test instances pass through managed code unchanged
public static IInterfaceTest pass_through(IInterfaceTest s)
{
return s;
}
Expand Down
5 changes: 2 additions & 3 deletions tests/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -1334,10 +1334,9 @@ def test_special_array_creation():
assert value[1].__class__ == inst.__class__
assert value.Length == 2

iface_class = ISayHello1(inst).__class__
value = Array[ISayHello1]([inst, inst])
assert value[0].__class__ == iface_class
assert value[1].__class__ == iface_class
assert value[0].__class__ == inst.__class__
assert value[1].__class__ == inst.__class__
assert value.Length == 2

inst = System.Exception("badness")
Expand Down
7 changes: 3 additions & 4 deletions tests/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ def test_generic_method_type_handling():
assert_generic_method_by_type(ShortEnum, ShortEnum.Zero)
assert_generic_method_by_type(System.Object, InterfaceTest())
assert_generic_method_by_type(InterfaceTest, InterfaceTest(), 1)
assert_generic_method_by_type(ISayHello1, InterfaceTest(), 1)


def test_correct_overload_selection():
Expand Down Expand Up @@ -546,11 +547,10 @@ def test_method_overload_selection_with_generic_types():
value = MethodTest.Overloaded.__overloads__[vtype](input_)
assert value.value.__class__ == inst.__class__

iface_class = ISayHello1(inst).__class__
vtype = GenericWrapper[ISayHello1]
input_ = vtype(inst)
value = MethodTest.Overloaded.__overloads__[vtype](input_)
assert value.value.__class__ == iface_class
assert value.value.__class__ == inst.__class__

vtype = System.Array[GenericWrapper[int]]
input_ = vtype([GenericWrapper[int](0), GenericWrapper[int](1)])
Expand Down Expand Up @@ -725,12 +725,11 @@ def test_overload_selection_with_arrays_of_generic_types():
assert value[0].value.__class__ == inst.__class__
assert value.Length == 2

iface_class = ISayHello1(inst).__class__
gtype = GenericWrapper[ISayHello1]
vtype = System.Array[gtype]
input_ = vtype([gtype(inst), gtype(inst)])
value = MethodTest.Overloaded.__overloads__[vtype](input_)
assert value[0].value.__class__ == iface_class
assert value[0].value.__class__ == inst.__class__
assert value.Length == 2


Expand Down
2 changes: 0 additions & 2 deletions tests/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ def test_explicit_cast_to_interface():
assert hasattr(i1, 'SayHello')
assert i1.SayHello() == 'hello 1'
assert not hasattr(i1, 'HelloProperty')
assert i1.__implementation__ == ob
assert i1.__raw_implementation__ == ob

i2 = Test.ISayHello2(ob)
assert type(i2).__name__ == 'ISayHello2'
Expand Down
9 changes: 3 additions & 6 deletions tests/test_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,8 @@ def test_explicit_overload_selection():
value = MethodTest.Overloaded.__overloads__[InterfaceTest](inst)
assert value.__class__ == inst.__class__

iface_class = ISayHello1(InterfaceTest()).__class__
value = MethodTest.Overloaded.__overloads__[ISayHello1](inst)
assert value.__class__ != inst.__class__
assert value.__class__ == iface_class
assert value.__class__ == inst.__class__

atype = Array[System.Object]
value = MethodTest.Overloaded.__overloads__[str, int, atype](
Expand Down Expand Up @@ -720,12 +718,11 @@ def test_overload_selection_with_array_types():
assert value[0].__class__ == inst.__class__
assert value[1].__class__ == inst.__class__

iface_class = ISayHello1(inst).__class__
vtype = Array[ISayHello1]
input_ = vtype([inst, inst])
value = MethodTest.Overloaded.__overloads__[vtype](input_)
assert value[0].__class__ == iface_class
assert value[1].__class__ == iface_class
assert value[0].__class__ == inst.__class__
assert value[1].__class__ == inst.__class__


def test_explicit_overload_selection_failure():
Expand Down
12 changes: 5 additions & 7 deletions tests/test_subclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,8 @@ def test_interface():
assert ob.bar("bar", 2) == "bar/bar"
assert FunctionsTest.test_bar(ob, "bar", 2) == "bar/bar"

# pass_through will convert from InterfaceTestClass -> IInterfaceTest,
# causing a new wrapper object to be created. Hence id will differ.
x = FunctionsTest.pass_through_interface(ob)
assert id(x) != id(ob)
x = FunctionsTest.pass_through(ob)
assert id(x) == id(ob)


def test_derived_class():
Expand Down Expand Up @@ -188,14 +186,14 @@ def test_create_instance():
assert id(x) == id(ob)

InterfaceTestClass = interface_test_class_fixture(test_create_instance.__name__)
ob2 = FunctionsTest.create_instance_interface(InterfaceTestClass)
ob2 = FunctionsTest.create_instance(InterfaceTestClass)
assert ob2.foo() == "InterfaceTestClass"
assert FunctionsTest.test_foo(ob2) == "InterfaceTestClass"
assert ob2.bar("bar", 2) == "bar/bar"
assert FunctionsTest.test_bar(ob2, "bar", 2) == "bar/bar"

y = FunctionsTest.pass_through_interface(ob2)
assert id(y) != id(ob2)
y = FunctionsTest.pass_through(ob2)
assert id(y) == id(ob2)


def test_events():
Expand Down