20.11. "nntplib" --- NNTP プロトコルクライアント
************************************************

**Source code:** Lib/nntplib.py

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

このモジュールでは、クラス "NNTP" を定義しています。このクラスは NNTP
プロトコルのクライアント側を実装しています。このモジュールを使えば、ニ
ュースリーダや記事投稿プログラム、または自動的にニュース記事を 処理す
るプログラムを実装することができます。NNTP (Network News Transfer
Protocol、ネットニュース転送プロトコル) の詳細については、インターネッ
ト **RFC 977** を参照してください。

以下にこのモジュールの使い方の小さな例を二つ示します。ニュースグループ
に関する統計情報を列挙し、最新 10 件の記事を出力するには以下のようにし
ます:

   >>> s = NNTP('news.gmane.org')
   >>> resp, count, first, last, name = s.group('gmane.comp.python.committers')
   >>> print 'Group', name, 'has', count, 'articles, range', first, 'to', last
   Group gmane.comp.python.committers has 1071 articles, range 1 to 1071
   >>> resp, subs = s.xhdr('subject', first + '-' + last)
   >>> for id, sub in subs[-10:]: print id, sub
   ...
   1062 Re: Mercurial Status?
   1063 Re: [python-committers]  (Windows) buildbots on 3.x
   1064 Re: Mercurial Status?
   1065 Re: Mercurial Status?
   1066 Python 2.6.6 status
   1067 Commit Privileges for Ask Solem
   1068 Re: Commit Privileges for Ask Solem
   1069 Re: Commit Privileges for Ask Solem
   1070 Re: Commit Privileges for Ask Solem
   1071 2.6.6 rc 2
   >>> s.quit()
   '205 Bye!'

ファイルから記事を投稿するには、以下のようにします。 (この例では記事番
号は有効な番号を指定していて、あなたがそのニュースグループに投稿する
権限を持っていると仮定しています)

   >>> s = NNTP('news.gmane.org')
   >>> f = open('articlefile')
   >>> s.post(f)
   '240 Article posted successfully.'
   >>> s.quit()
   '205 Bye!'

このモジュール自体では以下の内容を定義しています:

class nntplib.NNTP(host[, port [, user[, password [, readermode] [, usenetrc]]]])

   ホスト *host* 上で動作し、ポート番号 *port* で要求待ちをしている
   NNTP サーバとの接続を表現する新たな "NNTP" クラスのインスタンスを返
   します。標準の *port* は 119 です。オプションの *user* および
   *password* が与えられているか、 または "/.netrc" に適切な認証情報が
   指定されていて *usenetrc* が真 (デフォルト) の場合、 "AUTHINFO
   USER" および "AUTHINFO PASS" 命令を使ってサーバに対して身元証明およ
   び認証を行います。オプションのフラグ *readermode* が真の場合、認証
   の実行に先立って "mode reader"  命令が送信されます。reader モードは
   、ローカルマシン上の NNTP サーバ に接続していて、 "group" のような
   reader 特有の命令を呼び出したい場合に便利なことがあります。予期せず
   "NNTPPermanentError" に遭遇したなら、 *readermode* を設定する必要が
   あるかもしれません。 *readermode* のデフォルト値は "None" です。
   *usenetrc* のデフォルト値は "True" です。

   バージョン 2.4 で変更: *usenetrc* 引数を追加しました.

exception nntplib.NNTPError

   標準の例外 "Exception" から派生しており、 "nntplib" モジュールが送
   出する全ての例外の基底クラスです。

exception nntplib.NNTPReplyError

   期待はずれの応答がサーバから返された場合に送出される例外です。以前
   のバージョンとの互換性のために、 "error_reply" はこのクラスと等価に
   なっています。

exception nntplib.NNTPTemporaryError

   エラーコードの範囲が 400-499 のエラーを受信した場合に送出される例外
   です。以前のバージョンとの互換性のために、 "error_temp" はこのクラ
   スと等価になっています。

exception nntplib.NNTPPermanentError

   エラーコードの範囲が 500-599 のエラーを受信した場合に送出される例外
   です。以前のバージョンとの互換性のために、 "error_perm" はこのクラ
   スと等価になっています。

exception nntplib.NNTPProtocolError

   サーバから返される応答が 1--5 の範囲の数字で始まっていない場合に送
   出される例外です。以前のバージョンとの互換性のために、
   "error_proto" はこのクラスと等価になっています。

exception nntplib.NNTPDataError

   応答データ中に何らかのエラーが存在する場合に送出される例外です。以
   前のバージョンとの互換性のために、 "error_data" はこのクラスと等価
   になっています。


20.11.1. NNTP オブジェクト
==========================

NNTP インスタンスは以下のメソッドを持っています。全てのメソッドにおけ
る戻り値のタプルで最初の要素となる *response* は、サーバの応答です: こ
の文字列は 3 桁の数字からなるコードで始まります。サーバの応答がエラー
を示す場合、上記のいずれかの例外が送出されます。

NNTP.getwelcome()

   サーバに最初に接続した際に送信される応答中のウェルカムメッセージを
   返します。(このメッセージには時に、ユーザにとって重要な免責事項や
   ヘルプ情報が入っています。)

NNTP.set_debuglevel(level)

   インスタンスのデバッグレベルを設定します。このメソッドは印字される
   デバッグ出力の量を制御します。標準では "0" に設定されていて、 これ
   はデバッグ出力を全く印字しません。 "1" はそこそこの量、一般に NNTP
   要求や応答あたり 1 行のデバッグ出力を生成します。値が "2" やそれ以
   上の場合、(メッセージテキストを含めて) NNTP 接続上で送受信された全
   ての内容を一行ごとにログ出力する、最大限のデバッグ出力を生成します
   。

NNTP.newgroups(date, time[, file])

   "NEWSGROUPS" 命令を送信します。 *date* 引数は "'yymmdd'" の形式を取
   り、日付を表します。 *time* 引数は "'hhmmss'" の形式をとり、時刻を
   表します。与えられた日付および時刻以後新たに出現したニュースグルー
   プ名のリストを *groups* として、 "(response, groups)" を返します。
   *file* 引数が指定されている場合、 "NEWGROUPS" コマンドの出力結果は
   ファイルに格納されます。 *file* が文字列の場合、この文字列をファイ
   ル名としてファイルをオープンし、書き込み後にクローズします。 *file*
   がファ イルオブジェクトの場合、オブジェクトの "write()" メソッドを
   呼び出して出力結果を格納します。 *file* が指定されている場合は戻り
   値として空の リストを返します。

NNTP.newnews(group, date, time[, file])

   "NEWNEWS" 命令を送信します。ここで、 *group* はグループ名または
   "'*'" で、 *date* および *time* は "newsgrups()" における引数と同じ
   意味を持ちます。 "(response, articles)" からなるペアを返し、
   *articles* はメッセージ ID のリストです。 *file* 引数が指定されてい
   る場合、 "NEWNEWS" コマンドの出力結果は ファイルに格納されます。
   *file* が文字列の場合、この文字列をファイル名としてファイルをオープ
   ンし、書き込み後にクローズします。 *file* がファ イルオブジェクトの
   場合、オブジェクトの "write()" メソッドを呼び出して出力結果を格納し
   ます。 *file* が指定されている場合は戻り値として空の リストを返しま
   す。

NNTP.list([file])

   "LIST" 命令を送信します。 "(response, list)"  からなるペアを返しま
   す。 *list* はタプルからなるリストです。各タプルは "(group, last,
   first, flag)" の形式をとり、 *group* がグループ名、 *last* および
   *first* はそれぞれ最新および最初の記事の記事番号 (を表す文字列)、そ
   して *flag* は投稿が可能な場合には "'y'", そうでない場合には "'n'",
   グループがモデレート (moderated) されている場合には "'m'" となりま
   す。(順番に注意してください: *last*, *first* の順です。) *file* 引
   数が指定されている場合、 "LIST" コマンドの出力結果は ファイルに格納
   されます。 *file* が文字列の場合、この文字列をファイル名としてファ
   イルをオープンし、書き込み後にクローズします。 *file* がファ イルオ
   ブジェクトの場合、オブジェクトの "write()" メソッドを呼び出して出力
   結果を格納します。 *file* が指定されている場合は戻り値として空の リ
   ストを返します。

NNTP.descriptions(grouppattern)

   "LIST NEWSGROUPS" 命令を送信します。 *grouppattern* は RFC2980 の定
   義に従う wildmat 文字列です (実際には、 DOS や UNIX のシェルワイル
   ドカード文字列と同じです)。 "(response,list)" からなるペアを返し、
   *list* はタプル "(name, title)" リストになります。

   バージョン 2.4 で追加.

NNTP.description(group)

   単一のグループ *group* から説明文字列を取り出します。 ('group' が実
   際には wildmat 文字列で) 複数のグループがマッチした場合、 最初にマ
   ッチしたものを返します。何もマッチしなければ空文字列を返します。

   このメソッドはサーバからの応答コードを省略します。応答コードが必要
   なら、 "descriptions()" を使ってください。

   バージョン 2.4 で追加.

NNTP.group(name)

   "GROUP" 命令を送信します。 *name* はグループ名です。タプル
   "(response, count, first, last, name)" を返します。 *count* はグル
   ープ中の記事数 (の推定値) で、 *first* はグループ中の最初の記事番号
   、 *last* はグループ中の 最新の記事番号、 *name* はグループ名です。
   記事番号は文字列で返されます。

NNTP.help([file])

   "HELP" 命令を送信します。 "(response, list)"  からなるペアを返しま
   す。 *list* はヘルプ文字列からなるリストです。 *file* 引数が指定さ
   れている場合、 "HELP" コマンドの出力結果はファイルに格納されます。
   *file* が文字列の場合、この文字列をファイル名 としてファイルをオー
   プンし、書き込み後にクローズします。 *file* がファイルオブジェクト
   の場合、オブジェクトの "write()" メソッドを呼び出し て出力結果を格
   納します。 *file* が指定されている場合は戻り値として空のリストを返
   します。

NNTP.stat(id)

   "STAT" 命令を送信します。 *id* は ("'<'" と "'>'" に囲まれた形式の)
   メッセージ ID か、 (文字列の) 記事番号です。 三つ組み "(response,
   number, id)" を返します。 *number* は (文字列の) 記事番号で、 *id*
   は ("'<'" と "'>'" に囲まれた形式の) メッセージ ID です。

NNTP.next()

   "NEXT" 命令を送信します。 "stat()" のような応答を返します。

NNTP.last()

   "LAST" 命令を送信します。 "stat()" のような応答を返します。

NNTP.head(id)

   "HEAD" 命令を送信します。 *id* は "stat()" におけるのと同じ意味を持
   ちます。 "(response, number, id, list)" からなるタプルを返します。
   最初の 3 要素は "stat()" と同じもので、 *list* は記事のヘッダからな
   るリスト (まだ解析されておらず、末尾の改行が取り去られたヘッダ行の
   リスト) です。

NNTP.body(id[, file])

   "BODY" 命令を送信します。 *id* は "stat()" におけるのと同じ意味を持
   ちます。 *file* 引数が与えられている場合、記事本体 (body) はファイ
   ルに保存されます。 *file* が文字列の場合、このメソッドはその名前を
   持つファイルオブジェクトを 開き、記事を書き込んで閉じます。 *file*
   がファイルオブジェクトの場合、 "write()" を呼び出して記事本体を記録
   します。 "head()" のような戻り値を返します。 *file* が与えられてい
   た場合、返される *list* は空のリストになります。

NNTP.article(id)

   "ARTICLE" 命令を送信します。 *id* は "stat()" におけるのと同じ意味
   を持ちます。 "head()" のような戻り値を返します。

NNTP.slave()

   "SLAVE" 命令を送信します。サーバの *response* を返します。

NNTP.xhdr(header, string[, file])

   "XHDR" 命令を送信します、この命令は RFC には定義されていませんが、
   一般に広まっている拡張です。 *header* 引数は、例えば "'subject'" と
   いったヘッダキーワードです。 *string* 引数は  "'first-last'" の形式
   でなければならず、ここで *first* および *last* は検索の対象とする記
   事範囲の最初と最後の記事番号です。 "(response, list)" のペアを返し
   ます。 *list* は "(id, text)" のペアからなるリストで、 *id* が (文
   字列で表した) 記事番号、 *text* がその記事の ヘッダテキストです。
   *file* 引数が指定されている場合、 "XHDR" コマンドの出力結果は ファ
   イルに格納されます。 *file* が文字列の場合、この文字列をファイル名
   としてファイルをオープンし、書き込み後にクローズします。 *file* が
   ファ イルオブジェクトの場合、オブジェクトの "write()" メソッドを呼
   び出して出力結果を格納します。 *file* が指定されている場合は戻り値
   として空の リストを返します。

NNTP.post(file)

   "POST" 命令を使って記事をポストします。 *file* 引数は開かれているフ
   ァイルオブジェクトで、その内容は "readline()" メソッドを使って EOF
   まで読み出されます。内容は必要なヘッダを含め、正しい形式のニュース
   記事でなければなりません。 "post()" メソッドは "." で始まる行を自動
   的にエスケープします。

NNTP.ihave(id, file)

   "IHAVE" 命令を送信します。 *id* は ("'<'" と "'>'" に囲まれた) メッ
   セージ ID です。 応答がエラーでない場合、 *file* を "post()" と全く
   同じように扱います。

NNTP.date()

   タプル "(response, date, time)" を返します。このタプルには
   "newnews()" および "newgroups()" メソッドに合った形式の、現在の日付
   および時刻が入っています。これはオプションの NNTP 拡張なので、全て
   のサーバでサポートされているとは限りません。

NNTP.xgtitle(name[, file])

   "XGTITLE" 命令を処理し、 "(response, list)" からなるペアを返します
   。 *list* は "(name, title)" を含むタプルのリストです。 *file* 引数
   が指定されている場合、 "XHDR" コマンドの出力結果は ファイルに格納さ
   れます。 *file* が文字列の場合、この文字列をファイル名としてファイ
   ルをオープンし、書き込み後にクローズします。 *file* がファ イルオブ
   ジェクトの場合、オブジェクトの "write()" メソッドを呼び出して出力結
   果を格納します。 *file* が指定されている場合は戻り値として空の リス
   トを返します。これはオプションの NNTP 拡張なので、全てのサーバでサ
   ポートされているとは限りません。

   RFC2980 では、 "この拡張は撤廃すべきである" と主張しています。
   "descriptions()" または "description()" を使うようにしてください。

NNTP.xover(start, end[, file])

   "(resp, list)" からなるペアを返します。 *list* はタプルからなるリス
   トで、各タプルは記事番号 *start*  および *end* の間に区切られた記事
   です。各タプルは "(article number, subject, poster, date, id,
   references, size, lines)" の形式をとります。 *file* 引数が指定され
   ている場合、 "XHDR" コマンドの出力結果は ファイルに格納されます。
   *file* が文字列の場合、この文字列をファイル名としてファイルをオープ
   ンし、書き込み後にクローズします。 *file* がファ イルオブジェクトの
   場合、オブジェクトの "write()" メソッドを呼び出して出力結果を格納し
   ます。 *file* が指定されている場合は戻り値として空の リストを返しま
   す。これはオプションの NNTP 拡張なので、全てのサーバでサポートされ
   ているとは限りません。

NNTP.xpath(id)

   "(resp, path)" からなるペアを返します。 *path* はメッセージ ID が
   *id* である記事のディレクトリパスです。 これはオプションの NNTP 拡
   張なので、全てのサーバでサポートされているとは限りません。

NNTP.quit()

   "QUIT" 命令を送信し、接続を閉じます。このメソッドを呼び出した後は、
   NTTP オブジェクトの他のいかなるメソッドも呼び出してはいけません。
