clj-python / clj-python/libpython-clj

py/with macro doesn't bind the return value of __enter__ method

オープン
#273 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
Clojure
スター
1.2k
フォーク
74
PR マージ指標
30日以内にマージされた PR はありません

説明

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 TARGET
hit_except = False

try:
    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:

with open('file.txt', 'r') as f:
    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

  1. 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)
  2. Update the macro to correctly bind the return value of __enter__()

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

src/libpython_clj2/python/with.clj#L45-L63 と test/libpython_clj2/python_test.clj#L167 にある既存のテストから始めます。enter が別のオブジェクトを返すコンテキストマネージャーを使ってカバレッジを追加し、バインドされた値がその戻り値であることと、既存の with の動作が引き続きパスすることを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
clojure, python
領域
tooling
issue の種類
バグ
難易度
2/5
見積もり時間
1〜3時間
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
58/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。