Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion src/runtime/TypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,13 @@ public static NewReference tp_getattro_dlr_proxy(BorrowedReference ob, BorrowedR
{
resolved = dynamicMemberAccessor.TryGetMember(dynamicObject, memberName, out value);
}
catch
catch (Exception e)
{
// Avoid wrapping the CLR exception via Converter.ToPython here: that would trigger
// CLR type initialisation which can re-enter this slot on the same live object,
// causing infinite recursion. A plain RuntimeError with the message is safe.
Runtime.PyErr_Clear();
Exceptions.SetError(Exceptions.RuntimeError, e.Message);
return default;
}

Expand Down
6 changes: 6 additions & 0 deletions src/testing/dlrtest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public override bool TrySetMember(SetMemberBinder binder, object value)
}
}

public class ThrowingGetDynamicObject : DynamicStorageObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
=> throw new InvalidOperationException($"TryGetMember failed for '{binder.Name}'");
}

public class ThrowingSetDynamicObject : DynamicStorageObject
{
public override bool TrySetMember(SetMemberBinder binder, object value)
Expand Down
9 changes: 9 additions & 0 deletions tests/test_dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from Python.Test import RejectingDeleteDynamicObject
from Python.Test import RejectingSetDynamicObject
from Python.Test import ThrowingDeleteDynamicObject
from Python.Test import ThrowingGetDynamicObject
from Python.Test import ThrowingSetDynamicObject


Expand Down Expand Up @@ -186,6 +187,14 @@ def test_trysetmember_false_raises_attributeerror_instead_of_silent_python_setat
assert not hasattr(obj, "typoed_name")


def test_trygetmember_exception_is_raised_in_python():
obj = ThrowingGetDynamicObject()
obj.AddDynamicMember("any_key", 1)

with pytest.raises(Exception, match="TryGetMember failed for 'any_key'"):
_ = obj.any_key


def test_trysetmember_exception_is_raised_in_python():
obj = ThrowingSetDynamicObject()

Expand Down
Loading