Redirecting stdout failure with help function inside `__repr__`

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

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

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
python
領域
tooling

調査の方向性

まず、報告された CPython バージョンで、contextlib.redirect_stdout、StringIO、help()、ネストした repr、およびインスタンスへの doc の代入を使って例を再現します。help() がオブジェクトをどのようにフォーマットし、1 回目と 2 回目の呼び出しで出力を書き込むかを追跡します。リダイレクトされた stdout で、再現により help() の出力が漏れなくなり、IndexError も発生しなくなれば完了です。

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

説明

interpreter-core type-bug

Bug report

Despite modifying sys.stdout, the help function appears to ignore it sometimes during nested usage within __repr__ and with instance __doc__ attributes.

Example:

from contextlib import redirect_stdout
from io import StringIO


class ReprDoc:
    """Class doc-string."""

    def __init__(self, value):
        self.__doc__ = value.__doc__
        self.value = value

    def __repr__(self):
        print("<===Starting Stdout Redirect===>")
        with redirect_stdout(StringIO()) as doc:
            help(self.value)
        print("<===Stopping Stdout Redirect===>")
        return doc.getvalue().splitlines()[2]


def foo():
    """Foo doc-string."""

help(ReprDoc(foo))
help(ReprDoc(foo))

Output:

<===Starting Stdout Redirect===>
<===Stopping Stdout Redirect===>
Help on ReprDoc in module __main__:

foo()
    Foo doc-string.

<===Starting Stdout Redirect===>
Help on function foo in module __main__:

foo()
    Foo doc-string.
<===Stopping Stdout Redirect===>
Traceback (most recent call last):
  ...
IndexError: list index out of range

Checking sys.stdout affirms it is correct at every step, and using print with the redirected stdout affirms that the problem comes from help itself.

I imagine this problem is related to the use of self.__doc__ assignments, though the behavior is very strange because it works the first time and then fails the second time.

Your environment

  • CPython versions tested on: >= 3.8
  • Operating system and architecture: Windows 11
主要言語
Python
スター
77.2k
フォーク
36k
平均マージ
1日 9時間
マージ済み PR(30日)
558

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

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

はじめの一歩

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

python/cpython のほかの issue

python/cpython の issue をすべて見る

似ている issue

Python の issue をもっと見る

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

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