29.2. "codeop" --- Pythonコードをコンパイルする
***********************************************

"codeop" モジュールは、 "code" モジュールで行われているようなPythonの
read-eval-printループをエミュレートするユーティリティを提供します。そ
のため、このモジュールを直接利用する場面はあまり無いでしょう。プログラ
ムにこのようなループを含めたい場合は、 "code" モジュールの方が便利です
。

この仕事には二つの部分があります:

1. 入力の一行がPythonの文として完全であるかどうかを見分けられること
   : 簡単に言えば、次が '">>>"' か、あるいは '"..."' かどうかを見分け
   ま す。

2. どのfuture文をユーザが入力したのかを覚えていること。したがって、
   実 質的にそれに続く入力をこれらとともにコンパイルすることができます
   。

"codeop" モジュールはこうしたことのそれぞれを行う方法とそれら両方を行
う方法を提供します。

前者は実行するには:

codeop.compile_command(source[, filename[, symbol]])

   Pythonコードの文字列であるべき *source* をコンパイルしてみて、
   *source* が有効なPythonコードの場合はコードオブジェクトを返します。
   このような場合、コードオブジェクトのファイル名属性は、デフォルトで
   "'<input>'" である *filename* でしょう。*source* が有効なPythonコー
   ドでは *ない* が、有効なPythonコードの接頭語である場合には、"None"
   を返します。

   *source* に問題がある場合は、例外を発生させます。無効なPython構文が
   ある場合は、 "SyntaxError" を発生させます。また、無効なリテラルがあ
   る場合は、 "OverflowError" または "ValueError" を発生させます。

   *symbol* 引数は *source* が文としてコンパイルされるか("'single'" 、
   デフォルト) 、または *式* としてコンパイルされるかを決定します
   ("'eval'")。他のどんな値も "ValueError" を発生させる原因となります
   。

   注釈: ソースの終わりに達する前に、成功した結果をもってパーサは構
     文解析 を止めることがあります。このような場合、後ろに続く記号はエ
     ラーと ならずに無視されます。例えば、バックスラッシュの後ろに改行
     が2つあ って、その後ろにゴミがあるかもしれません。パーサのAPIがよ
     り良くな ればすぐに、この挙動は修正されるでしょう。

class codeop.Compile

   このクラスのインスタンスは組み込み関数 "compile()" とシグネチャが一
   致する "__call__()" メソッドを持っていますが、インスタンスが
   "__future__" 文を含むプログラムテキストをコンパイルする場合は、イン
   スタンスは有効なその文とともに続くすべてのプログラムテキストを'覚え
   ていて'コンパイルするという違いがあります。

class codeop.CommandCompiler

   このクラスのインスタンスは "compile_command()" とシグネチャが一致す
   る "__call__()" メソッドを持っています。インスタンスが "__future__"
   文を含むプログラムテキストをコンパイルする場合に、インスタンスは有
   効なその文とともにそれに続くすべてのプログラムテキストを'覚えていて
   'コンパイルするという違いがあります。

バージョン間の互換性についての注意: "Compile" と "CommandCompiler" は
Python 2.2 で導入されました。2.2 の future-tracking 機能を有効にするだ
けでなく、 2.1 と Python のより以前のバージョンとの互換性も保ちたい場
合は、次のように書くことができます

   try:
       from codeop import CommandCompiler
       compile_command = CommandCompiler()
       del CommandCompiler
   except ImportError:
       from codeop import compile_command

これは影響の小さい変更ですが、あなたのプログラムにおそらく望まれないグ
ローバル状態を導入します。または、次のように書くこともできます:

   try:
       from codeop import CommandCompiler
   except ImportError:
       def CommandCompiler():
           from codeop import compile_command
           return compile_command

そして、新たなコンパイラオブジェクトが必要となるたびに
"CommandCompiler" を呼び出します。
