高度なパターン—ドキュメントをクリックします

提供:Dev Guides
Click/docs/7.x/advanced
移動先:案内検索

高度なパターン

ライブラリ自体に実装されている一般的な機能に加えて、Clickを拡張することで実装できるパターンは無数にあります。 このページでは、何を達成できるかについての洞察を得る必要があります。

コマンドエイリアス

多くのツールはコマンドのエイリアスをサポートしています(コマンドエイリアスの例を参照)。 たとえば、gitを構成できます。 他のツールも、エイリアスを自動的に短縮することにより、エイリアスの自動検出をサポートしています。

Clickはこれをそのままではサポートしていませんが、 Group またはその他の MultiCommand をカスタマイズしてこの機能を提供するのは非常に簡単です。

カスタムマルチコマンドで説明されているように、マルチコマンドは list_commands()get_command()の2つのメソッドを提供できます。 この特定のケースでは、混乱を避けるためにヘルプページでエイリアスを列挙したくないので、後者をオーバーライドするだけで済みます。

次の例では、コマンドのプレフィックスを受け入れる Group のサブクラスを実装します。 pushというコマンドがある場合、pusをエイリアスとして受け入れます(一意である限り)。

そして、次のように使用できます。


パラメータの変更

これまで見てきたように、パラメーター(オプションと引数)はコマンドコールバックに転送されます。 パラメータがコールバックに渡されないようにする一般的な方法の1つは、パラメータを完全に非表示にするパラメータへの expose_value 引数です。 これが機能する方法は、 Context オブジェクトがすべてのパラメーターの辞書である params 属性を持っていることです。 その辞書にあるものはすべて、コールバックに渡されます。

これは、追加パラメーターを作成するために使用できます。 通常、このパターンは推奨されませんが、場合によっては役立つことがあります。 少なくとも、システムがこのように機能することを知っておくのは良いことです。

この場合、コールバックは変更されていないURLを返しますが、2番目のfp値もコールバックに渡します。 ただし、より推奨されるのは、ラッパーで情報を渡すことです。


トークンの正規化

バージョン2.0の新機能。


Click 2.0以降、トークンの正規化に使用される関数を提供することが可能になりました。 トークンは、オプション名、選択値、またはコマンド値です。 これは、たとえば、大文字と小文字を区別しないオプションを実装するために使用できます。

この機能を使用するには、トークンの正規化を実行する関数をコンテキストに渡す必要があります。 たとえば、トークンを小文字に変換する関数を作成できます。

そして、それがコマンドラインでどのように機能するか:


他のコマンドの呼び出し

あるコマンドを別のコマンドから呼び出すことが興味深い場合があります。 これは一般的にクリックでは推奨されないパターンですが、それでも可能です。 このために、 Context.invoke()または Context.forward()メソッドを使用できます。

これらは同様に機能しますが、 Context.invoke()は、呼び出し元として指定した引数を使用して別のコマンドを呼び出すだけですが、 Context.forward()はからの引数を入力します。現在のコマンド。 どちらも最初の引数としてコマンドを受け入れ、他のすべては期待どおりに渡されます。

例:

そしてそれはどのように見えるか:


コールバック評価順序

Clickは、コールバックを呼び出す前に、プログラマーが定義した引数の順序とユーザーが定義した引数の順序を調整しようとするという点で、他のコマンドラインパーサーとは少し異なります。

これは、複雑なパターンをoptparseまたは他のシステムからClickに移植するときに理解する重要な概念です。 optparseでのパラメーターのコールバック呼び出しは解析ステップの一部として発生しますが、Clickでのコールバック呼び出しは解析後に発生します。

主な違いは、optparseでは、コールバックは発生時に生の値で呼び出されるのに対し、Clickのコールバックは値が完全に変換された後に呼び出されることです。

一般に、呼び出しの順序は、ユーザーがスクリプトに引数を提供する順序によって決まります。 --fooというオプションと--barというオプションがあり、ユーザーがそれを--bar --fooと呼ぶと、barのコールバックがその前に発生します。 fooの場合。

このルールには、知っておくべき重要な3つの例外があります。

意気込み:

オプションは「熱心」に設定できます。 すべての熱心なパラメーターは、すべての非熱心なパラメーターの前に評価されますが、ユーザーがコマンドラインで指定した順序で評価されます。

これは、--help--versionのように実行および終了するパラメーターにとって重要です。 どちらも熱心なパラメータですが、コマンドラインで最初に来るパラメータはすべて勝ち、プログラムを終了します。

繰り返されるパラメーター:

オプションまたは引数が繰り返されるためにコマンドラインで複数の場所に分割された場合(たとえば、--exclude foo --include baz --exclude bar)、コールバックは最初のオプションの位置に基づいて起動します。 この場合、コールバックはexcludeに対して起動し、両方のオプション(foobar)が渡され、includeのコールバックが起動します。 bazのみ。

パラメータで複数のバージョンが許可されていない場合でも、Clickは最初の位置を受け入れますが、最後を除くすべての値を無視することに注意してください。 これは、デフォルトを設定するシェルエイリアスを介して構成可能にするためです。

欠落しているパラメーター:

コマンドラインでパラメータが定義されていない場合でも、コールバックは発生します。 これは、未定義の値がコールバックを起動しないoptparseでの動作とは異なります。 欠落しているパラメーターは、最後にコールバックを起動します。これにより、前に来たパラメーターの値をデフォルトにすることができます。

ほとんどの場合、これについて心配する必要はありませんが、一部の高度なケースでどのように機能するかを知ることは重要です。


不明なオプションの転送

状況によっては、さらに手動で処理するためにすべての不明なオプションを受け入れることができるのは興味深いことです。 Clickは一般的にClick4.0の時点でそれを行うことができますが、問題の性質にあるいくつかの制限があります。 これのサポートは、ignore_unknown_optionsと呼ばれるパーサーフラグによって提供されます。このフラグは、パーサーに、すべての不明なオプションを収集し、解析エラーをトリガーする代わりに残りの引数にそれらを置くように指示します。

これは通常、2つの異なる方法でアクティブ化できます。

  1. ignore_unknown_options 属性を変更することにより、カスタム Command サブクラスで有効にできます。
  2. コンテキストクラス( Context.ignore_unknown_options )で同じ名前の属性を変更することで有効にできます。 これは、コマンドのcontext_settings辞書を使用して変更するのが最適です。

ほとんどの場合、最も簡単な解決策は2番目です。 動作が変更されたら、何かがそれらの残りのオプションを選択する必要があります(この時点で引数と見なされます)。 これについても、2つのオプションがあります。

  1. pass_context()を使用して、コンテキストを渡すことができます。 これは、 ignore_unknown_options に加えて、 allow_extra_args も設定した場合にのみ機能します。そうしないと、コマンドが中止され、引数が残っているというエラーが発生します。 このソリューションを使用する場合、追加の引数は Context.args に収集されます。
  2. nargsを -1 に設定して argument()をアタッチすると、残りの引数がすべて消費されます。 この場合、 type を UNPROCESSED に設定して、これらの引数での文字列処理を回避することをお勧めします。そうしないと、引数が自動的にUnicode文字列に強制され、多くの場合、必要なものではなくなります。

最終的には、次のような結果になります。

そしてそれはどのように見えるか:

冗長性フラグがClickによって処理されることがわかるように、他のすべては timeit_args 変数に入れられ、さらに処理されます。これにより、たとえば、サブプロセスを呼び出すことができます。 この未処理のフラグの無視がどのように発生するかについて知っておくべき重要なことがいくつかあります。

  • 不明な長いオプションは通常無視され、まったく処理されません。 したがって、たとえば--foo=barまたは--foo barが渡された場合、通常はそのようになります。 オプションが引数を受け入れるかどうかをパーサーが知ることができないため、bar部分が引数として扱われる可能性があることに注意してください。
  • 不明な短いオプションは、必要に応じて部分的に処理され、再組み立てされる場合があります。 たとえば、上記の例では、詳細モードを有効にする-vというオプションがあります。 コマンドが-vaで無視される場合、-vの部分はClickによって処理され(既知のとおり)、-aはさらに処理するために残りのパラメーターになります。 。
  • 実行する予定によっては、引数とオプションの混合を許可しないようにパーサーに指示する散在する引数( allow_interspersed_args )を無効にすることで、ある程度の成功を収めることができます。 状況によっては、これにより結果が改善される場合があります。

一般に、独自のコマンドからのオプションと引数、および別のアプリケーションからのコマンドを組み合わせて処理することはお勧めしませんが、回避できる場合は、そうする必要があります。 一部の引数を自分で処理するよりも、サブコマンドの下にあるすべてのものを別のアプリケーションに転送することをお勧めします。


グローバルコンテキストアクセス

バージョン5.0の新機能。


Click 5.0以降では、 get_current_context()関数を使用して、同じスレッド内のどこからでも現在のコンテキストにアクセスできます。 これは主に、コンテキストにバインドされたオブジェクトと、実行時の動作をカスタマイズするためにオブジェクトに格納されているいくつかのフラグにアクセスする場合に役立ちます。 たとえば、 echo()関数はこれを実行して、 color フラグのデフォルト値を推測します。

使用例:

def get_current_command_name():
    return click.get_current_context().info_name

これは現在のスレッド内でのみ機能することに注意してください。 追加のスレッドを生成すると、それらのスレッドは現在のコンテキストを参照することができなくなります。 別のスレッドにこのコンテキストを参照する機能を与える場合は、スレッド内のコンテキストをコンテキストマネージャーとして使用する必要があります。

def spawn_thread(ctx, func):
    def wrapper():
        with ctx:
            func()
    t = threading.Thread(target=wrapper)
    t.start()
    return t

これで、スレッド関数はメインスレッドと同じようにコンテキストにアクセスできます。 ただし、これをスレッドに使用する場合は、コンテキストの大部分がスレッドセーフではないため、非常に注意する必要があります。 コンテキストからの読み取りのみが許可されており、コンテキストに変更を加えることはできません。