Skip to content

dlr branch fix - Propagate exceptions from TryGetMember in tp_getattro_dlr_proxy#2718

Merged
filmor merged 1 commit into
pythonnet:dlrfrom
greateggsgreg:dlr
May 11, 2026
Merged

dlr branch fix - Propagate exceptions from TryGetMember in tp_getattro_dlr_proxy#2718
filmor merged 1 commit into
pythonnet:dlrfrom
greateggsgreg:dlr

Conversation

@greateggsgreg
Copy link
Copy Markdown
Contributor

@greateggsgreg greateggsgreg commented May 9, 2026

Adds the symmetric exception-propagation fix to the DLR getter, completing the fix called out by @lostmsu in the #2706 review.

Problem

tp_getattro_dlr_proxy swallowed exceptions raised from TryGetMember and returned default to Python while the prior AttributeError from PyObject_GenericGetAttr was still set. Callers therefore observed a misleading AttributeError instead of the real failure — exactly the kind of silent error-masking the reviewer flagged for the setter (which was fixed in d629b87).

Fix

Set a Python exception in the catch block before returning default.

We use Exceptions.SetError(Exceptions.RuntimeError, e.Message) rather than Exceptions.SetError(e) deliberately. Wrapping the CLR exception object via Converter.ToPython triggers CLR type initialisation, which can re-enter tp_getattro_dlr_proxy on the same live dynamic object and recurse infinitely. A plain RuntimeError with the message string preserves the diagnostic information without that hazard.

Test

Adds ThrowingGetDynamicObject to dlrtest.cs and test_trygetmember_exception_is_raised_in_python to tests/test_dynamic.py, mirroring the existing coverage for TrySetMember/TryDeleteMember exception paths.

The dynamic getter swallowed any exception from TryGetMember and
returned default to Python with the prior AttributeError still set,
so user code observed a misleading AttributeError instead of the real
failure.

Set a Python exception in the catch arm. We use RuntimeError with the
message string rather than Converter.ToPython(e) because wrapping the
CLR exception object can trigger type initialisation that re-enters
this same slot on the live dynamic object, producing infinite
recursion.

Mirrors the symmetry already present in the setter (pythonnet#2706 review,
@lostmsu) and adds a regression test alongside the existing
ThrowingSetDynamicObject coverage.
@greateggsgreg greateggsgreg changed the title Propagate exceptions from TryGetMember in tp_getattro_dlr_proxy dlr branch fix - Propagate exceptions from TryGetMember in tp_getattro_dlr_proxy May 9, 2026
@filmor filmor merged commit da48ef7 into pythonnet:dlr May 11, 2026
27 of 29 checks passed
filmor pushed a commit that referenced this pull request May 12, 2026
The dynamic getter swallowed any exception from TryGetMember and
returned default to Python with the prior AttributeError still set,
so user code observed a misleading AttributeError instead of the real
failure.

Set a Python exception in the catch arm. We use RuntimeError with the
message string rather than Converter.ToPython(e) because wrapping the
CLR exception object can trigger type initialisation that re-enters
this same slot on the live dynamic object, producing infinite
recursion.

Mirrors the symmetry already present in the setter (#2706 review,
@lostmsu) and adds a regression test alongside the existing
ThrowingSetDynamicObject coverage.
filmor pushed a commit that referenced this pull request May 12, 2026
The dynamic getter swallowed any exception from TryGetMember and
returned default to Python with the prior AttributeError still set,
so user code observed a misleading AttributeError instead of the real
failure.

Set a Python exception in the catch arm. We use RuntimeError with the
message string rather than Converter.ToPython(e) because wrapping the
CLR exception object can trigger type initialisation that re-enters
this same slot on the live dynamic object, producing infinite
recursion.

Mirrors the symmetry already present in the setter (#2706 review,
@lostmsu) and adds a regression test alongside the existing
ThrowingSetDynamicObject coverage.
filmor pushed a commit that referenced this pull request May 13, 2026
The dynamic getter swallowed any exception from TryGetMember and
returned default to Python with the prior AttributeError still set,
so user code observed a misleading AttributeError instead of the real
failure.

Set a Python exception in the catch arm. We use RuntimeError with the
message string rather than Converter.ToPython(e) because wrapping the
CLR exception object can trigger type initialisation that re-enters
this same slot on the live dynamic object, producing infinite
recursion.

Mirrors the symmetry already present in the setter (#2706 review,
@lostmsu) and adds a regression test alongside the existing
ThrowingSetDynamicObject coverage.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants