"reprlib" --- もう一つの "repr()" の実装
****************************************

**ソースコード:** Lib/reprlib.py

======================================================================

"reprlib" モジュールは、結果の文字列のサイズに対する制限付きでオブジェ
クト表現を生成するための手段を提供します。これは Python デバッガの中で
使用されており、他の文脈でも同様に役に立つかもしれません。

このモジュールはクラスとインスタンス、それに関数を提供します:

class reprlib.Repr(*, maxlevel=6, maxtuple=6, maxlist=6, maxarray=5, maxdict=4, maxset=6, maxfrozenset=6, maxdeque=6, maxstring=30, maxlong=40, maxother=30, fillvalue='...', indent=None)

   組み込み関数 "repr()" に似た関数を実装するために役に立つフォーマッ
   ト用サービスを提供します。 過度に長い表現を作り出さないようにするた
   めの大きさの制限をオブジェクト型ごとに設定できます。

   コンストラクタのキーワード引数を使うと、"Repr" インスタンスの属性を
   簡単に設定できます。 例えば、次のように初期化できます。

      aRepr = reprlib.Repr(maxlevel=3)

   は、次のコードと等しいです:

      aRepr = reprlib.Repr()
      aRepr.maxlevel = 3

   "Repr" の属性について詳しくは Repr Objects の節を参照してください。

   バージョン 3.12 で変更: キーワード引数で属性を設定できるようになり
   ました。

reprlib.aRepr

   これは下で説明される "repr()" 関数を提供するために使われる "Repr"
   のインスタンスです。このオブジェクトの属性を変更すると、 "repr()"
   と Python デバッガが使うサイズ制限に影響します。

reprlib.repr(obj)

   これは "aRepr" の "repr()" メソッドです。同じ名前の組み込み関数が返
   す文字列と似ていますが、最大サイズに制限のある文字列を返します。

サイズを制限するツールに加えて、このモジュールは "__repr__()" の再帰呼
び出しを検出し、代わりにプレースホルダーの文字列を返すデコレータも提供
します。

@reprlib.recursive_repr(fillvalue='...')

   同じスレッド内での再帰呼び出しを検出する、"__repr__()" メソッド用の
   デコレータです。 再帰呼び出しが行われた場合は *fillvalue* を返し、
   それ以外の場合は通常の "__repr__()" 呼び出しを行います。 例えば、次
   のように使います:

      >>> from reprlib import recursive_repr
      >>> class MyList(list):
      ...     @recursive_repr()
      ...     def __repr__(self):
      ...         return '<' + '|'.join(map(repr, self)) + '>'
      ...
      >>> m = MyList('abc')
      >>> m.append(m)
      >>> m.append('x')
      >>> print(m)
      <'a'|'b'|'c'|...|'x'>

   Added in version 3.2.


Reprオブジェクト
================

"Repr" インスタンスはオブジェクト型毎に表現する文字列のサイズを制限す
るために使えるいくつかの属性と、特定のオブジェクト型をフォーマットする
メソッドを提供します。

Repr.fillvalue

   再帰的な参照に対して表示する文字列です。 デフォルトは "..." です。

   Added in version 3.11.

Repr.maxlevel

   再帰的な表現を作る場合の深さ制限。デフォルトは "6" です。

Repr.maxdict
Repr.maxlist
Repr.maxtuple
Repr.maxset
Repr.maxfrozenset
Repr.maxdeque
Repr.maxarray

   指定されたオブジェクト型に対するエントリ表現の数についての制限。
   "maxdict" に対するデフォルトは "4" で、 "maxarray" は "5" 、その他
   に対しては "6" です。

Repr.maxlong

   整数の表現のおける文字数の最大値。中央の数字が抜け落ちます。デフォ
   ルトは "40" です。

Repr.maxstring

   文字列の表現における文字数の制限。文字列の"通常の"表現は文字の「元
   」として使われることに注意してください。表現にエスケープシーケンス
   が必要とされる場合、表現が短縮されるときにこれらのエスケープシーケ
   ンスの形式は崩れます。デフォルトは "30" です。

Repr.maxother

   この制限は "Repr" オブジェクトに利用できる特定のフォーマットメソッ
   ドがないオブジェクト型のサイズをコントロールするために使われます。
   "maxstring" と同じようなやり方で適用されます。デフォルトは "20" で
   す。

Repr.indent

   この属性が "None" (デフォルト) の場合、標準の "repr()" と同様に、改
   行やインデントなしで出力を書式化します。 例えば、次のようになります
   :

      >>> example = [
      ...     1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham']
      >>> import reprlib
      >>> aRepr = reprlib.Repr()
      >>> print(aRepr.repr(example))
      [1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham']

   "indent" に文字列を設定すると、再帰の各レベルを別の行に配置し、その
   文字列でインデントします:

      >>> aRepr.indent = '-->'
      >>> print(aRepr.repr(example))
      [
      -->1,
      -->'spam',
      -->{
      -->-->'a': 2,
      -->-->'b': 'spam eggs',
      -->-->'c': {
      -->-->-->3: 4.5,
      -->-->-->6: [],
      -->-->},
      -->},
      -->'ham',
      ]

   "indent" に正の整数を設定すると、その個数の空白からなる文字列を設定
   した場合と同じように動作します:

      >>> aRepr.indent = 4
      >>> print(aRepr.repr(example))
      [
          1,
          'spam',
          {
              'a': 2,
              'b': 'spam eggs',
              'c': {
                  3: 4.5,
                  6: [],
              },
          },
          'ham',
      ]

   Added in version 3.12.

Repr.repr(obj)

   このインスタンスで設定されたフォーマットを使う、組み込み "repr()"
   と等価なもの。

Repr.repr1(obj, level)

   "repr()" が使う再帰的な実装。 *obj* の型を使ってどのフォーマットメ
   ソッドを呼び出すかを決定し、それに *obj* と *level* を渡します。 再
   帰呼び出しにおいて *level* の値に対して "level - 1" を与える再帰的
   なフォーマットを実行するために、型に固有のメソッドは "repr1()" を呼
   び出します。

Repr.repr_TYPE(obj, level)

   型名に基づく名前をもつメソッドとして、特定の型に対するフォーマット
   メソッドは実装されます。メソッド名では、 **TYPE** は
   "'_'.join(type(obj).__name__.split())" に置き換えられます。これらの
   メソッドへのディスパッチは "repr1()" によって処理されます。再帰的に
   値をフォーマットする必要がある型固有のメソッドは、
   "self.repr1(subobj, level - 1)" を呼び出します。


Reprオブジェクトをサブクラス化する
==================================

"Repr.repr1()" は動的なディスパッチを使うため、"Repr" のサブクラスで別
の組み込みオブジェクト型への対応を追加したり、サポート済みの型の扱いを
変更したりできます。 次の例は、ファイルオブジェクト向けの特別な処理を
追加する方法を示します:

   import reprlib
   import sys

   class MyRepr(reprlib.Repr):

       def repr_TextIOWrapper(self, obj, level):
           if obj.name in {'<stdin>', '<stdout>', '<stderr>'}:
               return obj.name
           return repr(obj)

   aRepr = MyRepr()
   print(aRepr.repr(sys.stdin))         # '<stdin>' と表示する

   <stdin>
