diff --git a/src/runtime/Types/InterfaceObject.cs b/src/runtime/Types/InterfaceObject.cs index 2d82392bf..536defd91 100644 --- a/src/runtime/Types/InterfaceObject.cs +++ b/src/runtime/Types/InterfaceObject.cs @@ -106,15 +106,34 @@ public static NewReference tp_getattro(BorrowedReference ob, BorrowedReference k } string? name = Runtime.GetManagedString(key); - if (name == "__implementation__") + if (name != null) { - return Converter.ToPython(clrObj.inst); - } - else if (name == "__raw_implementation__") - { - return CLRObject.GetReference(clrObj.inst); + if (name == "__implementation__") + { + return Converter.ToPython(clrObj.inst); + } + else if (name == "__raw_implementation__") + { + return CLRObject.GetReference(clrObj.inst); + } + else + { + // try get attr from pure interface wrapper + var value = Runtime.PyObject_GenericGetAttr(ob, key); + if (Exceptions.ErrorOccurred()) + { + // if that didn't work, clear errors + // and try get from wrapped object + Exceptions.Clear(); + + using var pyObj = Converter.ToPython(clrObj.inst); + return Runtime.PyObject_GenericGetAttr(pyObj.Borrow(), key); + } + return value; + } } + return Runtime.PyObject_GenericGetAttr(ob, key); } diff --git a/tests/test_interface.py b/tests/test_interface.py index 557e8da80..b626c12b4 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -61,7 +61,7 @@ def test_explicit_cast_to_interface(): assert type(i1).__name__ == 'ISayHello1' assert hasattr(i1, 'SayHello') assert i1.SayHello() == 'hello 1' - assert not hasattr(i1, 'HelloProperty') + assert hasattr(i1, 'HelloProperty') assert i1.__implementation__ == ob assert i1.__raw_implementation__ == ob @@ -69,7 +69,7 @@ def test_explicit_cast_to_interface(): assert type(i2).__name__ == 'ISayHello2' assert i2.SayHello() == 'hello 2' assert hasattr(i2, 'SayHello') - assert not hasattr(i2, 'HelloProperty') + assert hasattr(i2, 'HelloProperty') def test_interface_object_returned_through_method():