サブパッケージ 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
感想¶
ここは特に問題ない。