Skip to content
Open
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
- Jan Krivanek ([@jakrivan](https://github.com/jakrivan))
- Jeff Reback ([@jreback](https://github.com/jreback))
- Jeff Robbins ([@jeff17robbins](https://github.com/jeff17robbins))
- João Neves ([@joaompneves](https://github.com/joaompneves))
- Joe Frayne ([@jfrayne](https://github.com/jfrayne))
- Joe Lidbetter ([@jmlidbetter](https://github.com/jmlidbetter))
- Joe Savage ([@s4v4g3](https://github.com/s4v4g3))
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].

### Added

- Added `ToPythonAs()` extension method to allow for explicit conversion using a specific type not known at build time (#2419)
- Added `ToPythonAs<T>()` extension method to allow for explicit conversion using a specific type (#2311)

### Changed

### Fixed
Expand Down
29 changes: 29 additions & 0 deletions src/embed_tests/Codecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,23 @@ public void ExceptionDecoded()
Assert.That(error.Message, Is.EqualTo(TestExceptionMessage));
}

[Test(Description = "Tests encoding of an object that explicitly implements an interface.")]
public void ExplicitObjectInterfaceEncoded()
{
var obj = new ExplicitInterfaceObject();
using var scope = Py.CreateScope();
scope.Exec(@"
def call(obj):
return dir(obj)
");
var callFunc = scope.Get("call");
// explicitly pass an interface (but not a generic type argument) to simulate a scenario where the type is not know at build time
var callArg = obj.ToPythonAs(typeof(IObjectInterface));
var members = callFunc.Invoke(callArg).As<string[]>();
CollectionAssert.Contains(members, nameof(IObjectInterface.MemberFromInterface));
CollectionAssert.DoesNotContain(members, nameof(ExplicitInterfaceObject.MemberFromObject));
}

[Test]
public void DateTimeDecoded()
{
Expand Down Expand Up @@ -519,4 +536,16 @@ public bool TryDecode<T>(PyObject pyObj, out T value)
return true;
}
}

interface IObjectInterface
{
int MemberFromInterface { get; }
}

class ExplicitInterfaceObject : IObjectInterface
{
int IObjectInterface.MemberFromInterface { get; }

public int MemberFromObject { get; }
}
}
7 changes: 6 additions & 1 deletion src/runtime/Converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -983,9 +983,14 @@ public static PyObject ToPython(this object? o)
}

public static PyObject ToPythonAs<T>(this T? o)
{
return ToPythonAs(o, typeof(T));
}

public static PyObject ToPythonAs(this object? o, Type type)
{
if (o is null) return Runtime.None;
return Converter.ToPython(o, typeof(T)).MoveToPyObject();
return Converter.ToPython(o, type).MoveToPyObject();
}
Comment thread
joaompneves marked this conversation as resolved.
}
}