コンソールプロトコル

Richは、カスタムオブジェクトにリッチフォーマット機能を追加するためのシンプルなプロトコルをサポートしており、色、スタイル、フォーマットを使用してオブジェクトをprint()できます。

これは、プレゼンテーションや、通常の__repr__文字列からは解析が難しい追加のデバッグ情報を表示するために使用します。

コンソールのカスタマイズ

オブジェクトのコンソール出力をカスタマイズする最も簡単な方法は、__rich__メソッドを実装することです。このメソッドは引数を受け取らず、Richがレンダリング方法を知っているオブジェクト、例えばTextTableなどを返します。プレーンな文字列を返すと、コンソールマークアップとしてレンダリングされます。次に例を示します。

class MyObject:
    def __rich__(self) -> str:
        return "[bold cyan]MyObject()"

MyObjectのインスタンスをprintまたはlogすると、太字のシアンでMyObject()としてレンダリングされます。もちろん、これをもっと有効に活用したいと思うでしょう。例えば、特殊な構文ハイライトを追加するなどです。

コンソールレンダリング

__rich__メソッドは、単一のレンダリング可能なオブジェクトに制限されています。より高度なレンダリングを行うには、クラスに__rich_console__メソッドを追加します。

__rich_console__メソッドは、ConsoleConsoleOptionsインスタンスを受け入れる必要があります。他のレンダリング可能なオブジェクトの反復可能オブジェクトを返す必要があります。つまり、リストのようなコンテナを返すこともできますが、一般的にはyield文を使用する方が実装が容易になります(メソッドをジェネレータにする)。

__rich_console__メソッドの例を次に示します。

from dataclasses import dataclass
from rich.console import Console, ConsoleOptions, RenderResult
from rich.table import Table

@dataclass
class Student:
    id: int
    name: str
    age: int
    def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
        yield f"[b]Student:[/b] #{self.id}"
        my_table = Table("Attribute", "Value")
        my_table.add_row("name", self.name)
        my_table.add_row("age", str(self.age))
        yield my_table

Studentインスタンスをprintすると、端末にシンプルなテーブルがレンダリングされます。

低レベルレンダリング

カスタムオブジェクトが端末にどのようにレンダリングされるかを完全に制御するには、Segmentオブジェクトをyieldします。セグメントは、テキストの一部とオプションのスタイルで構成されます。MyObjectインスタンスをレンダリングする際に、次の例ではマルチカラーのテキストを書き込みます。

class MyObject:
    def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
        yield Segment("My", Style(color="magenta"))
        yield Segment("Object", Style(color="green"))
        yield Segment("()", Style(color="cyan"))

レンダリング可能なオブジェクトの測定

Richは、オブジェクトをレンダリングする際に何文字必要になるかを知る必要がある場合があります。例えば、Tableクラスは、この情報を使用してカラムの最適な寸法を計算します。Richモジュールのレンダリング可能なオブジェクトのいずれかを使用していない場合は、ConsoleConsoleOptionsを受け取り、Measurementオブジェクトを返す__rich_measure__メソッドを提供する必要があります。Measurementオブジェクトには、レンダリングに必要な文字数の_最小値_と_最大値_が含まれている必要があります。

例えば、チェス盤をレンダリングする場合、レンダリングには最低8文字が必要です。最大値は、利用可能な最大幅(中央揃えのボードを想定)のままにすることができます。

class ChessBoard:
    def __rich_measure__(self, console: Console, options: ConsoleOptions) -> Measurement:
        return Measurement(8, options.max_width)