サブパッケージ docutils.readers
¶
本節では Docutils のサブパッケージ docutils.readers
を見ていく。このサブパッケージが提供する機能は、入力データから文書情報を読み取り、メモリ内に構文木オブジェクトを生成するクラス群ということになる。
クラス図¶
クラス docutils.readers.Reader
を中心とした簡易クラス図を以下に示す。これまでに述べたクラスについてはグレーアウトしたり、記載そのものを省いたりしている。
スーパークラスの
Reader
にはさらにその上にスーパークラスとしてComponent
があるが紙幅の都合上省略した。クラスComponent
については 基礎クラス群 を参照。クラス
Parser
については サブパッケージ docutils.parsers を参照。クラス
Input
については モジュール docutils.io を参照。
クラス Reader
¶
クラス Reader
は入力から文書テキストを読み取り、構文木オブジェクトを構築するための全てのクラスの共通スーパークラスという位置づけだ。
文書テキストから構文木オブジェクトを生成するために、クライアントは Input
と
Parser
の型を両方指定する。
データ¶
次の二つはクラスデータだ。
component_type
スーパークラスの同名属性の上書き。値は文字列
reader
で固定。config_section
スーパークラスの同名属性の上書き。値は文字列
readers
で固定。
以下はオブジェクトのメンバーデータだ。
self.parser
クラス
docutils.parsers.Parser
のサブクラスのオブジェクト。これが生の入力テキストデータを構文解析する。self.source
クラス
docutils.io.Input
のサブクラスのオブジェクト。生のテキストデータそのものか、テキストファイルを指すか、あるいはそれ以外の何かか。self.input
入力テキストデータ。
self.source
から直接得られる。self.document
構文木オブジェクト。文字列
self.input
を構文解析して得られるオブジェクト。self.settings
何かの構成項目を表現するオブジェクトらしいが、この階層では
new_document
関連でパラメーターとして振る舞う。
メソッド¶
かなり単純な構成になっている。
__init__(self, parser=None, parser_name=None)
オブジェクトを初期化する。
オプションとして、このタイミングで構文解析オブジェクトをセットアップできる。しない場合は別途
set_parser
をクライアントが明示的に呼ぶ。get_transforms(self)
スーパークラス
Component
からの上書き。さらに三種類の変換処理を増やしてある。set_parser(self, parser_name)
この読み取りオブジェクトの管理する構文解析オブジェクトをセットアップする。
read(self, source, parser, settings)
入力から情報を読み取るメソッド。具体的には読み取りアンド解析。
クライアントに対する主なインターフェイスとなるメソッド。
設計意図としてはこのメソッドは上書きされない。
呼び出し直後に
self.document
の構築が完了した状態になる。
parse(self)
文字列
self.input
を構文解析して構文木オブジェクトself.document
を構築する。設計的にはこのメソッドは private 扱いと見える。少なくとも public のつもりではない。クライアントが
Reader
オブジェクトに対してparser
を呼び出す意図はないだろう。
new_document(self)
クラス
document
のオブジェクトを生成して返す。実装は
utils.new_document
を呼び出すだけ。メソッドの立場は、GoF デザインパターンの Factory Method パターンにおけるオブジェクト生成メソッドだろう。ただし、これを上書きするサブクラスが全くない。
サブクラス¶
クラス
ReReader
はget_transforms
が劣化したReader
という扱い。書き出しクラスUnfilteredWriter
とともに用いられることが多い。クラス
doctree.Reader
はReReader
のサブクラスだ。ここではメソッドparse
を上書きして、self.document == self.input
としている。つまり構文木オブジェクトがもうあるので、二度解析しないということか。クラス
standalone.Reader
はReader
よりも変換処理が増えている。クラス
pep.Reader
はstandalone.Reader
のサブクラスであるが、変換処理の一部が変更されている。
オブジェクト生成¶
クライアントは所望のモジュールから読み取りクラスそのものではなく、関数
docutils.readers.get_reader_class
を import
する。この関数に名前を渡すと、クラスが返ってくるので、呼び出し元がそこからコンストラクターを呼び出す。
この手法は Docutils で多用されている。
クライアント¶
モジュール docutils.core
でオブジェクトの生成処理が確認できる。
def set_reader(self, reader_name, parser, parser_name):
"""Set `self.reader` by name."""
reader_class = readers.get_reader_class(reader_name)
self.reader = reader_class(parser, parser_name)
self.parser = self.reader.parser
感想¶
ここは特に問題ない。