You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
py/with macro doesn't bind the return value of __enter__ method #273
The py/with macro implementation doesn't correctly follow Python's with statement semantics. According to the Python documentation, the value bound in a with statement should be the return value of calling __enter__() on the context manager:
manager= (EXPRESSION)
enter=type(manager).__enter__exit=type(manager).__exit__value=enter(manager) # This value should be bound to TARGEThit_except=Falsetry:
TARGET=value# TARGET gets the return value of enter(manager)SUITE
...
Current Implementation
The current macro (with.clj#L45-L63) calls __enter__ but discards its return value:
(py-fn/call-attr ~varname "__enter__"nil) ; Return value is ignored
(try
(let [retval# (do ~@body)]
...
Expected Behavior
The bound variable should receive the return value of __enter__(), not the context manager itself:
(let [enter-result# (py-fn/call-attr ~varname "__enter__"nil)]
(try
(let [~varname enter-result# ; Rebind to __enter__'s return value
retval# (do ~@body)]
...
Why Current Tests Pass
The existing test in python_test.clj#L167 uses a WithObjClass where __enter__() returns None (implicitly), and the test methods are called on the original object. This masks the bug.
Real-World Example
A common Python pattern that fails with the current implementation:
withopen('file.txt', 'r') asf:
content=f.read() # f should be the file object returned by __enter__
With the current macro, f would be bound to the unopened file path/manager rather than the file object returned by __enter__().
Next Steps
Add test cases that verify this behavior (e.g., update WithObjClass.__enter__ to return a different object, or test with Python's built-in file context manager)
Update the macro to correctly bind the return value of __enter__()
Activity