(機械翻訳) 高度な設定

アプリケーションの拡張性をサポートするため、:app: Pyramid:term:` Configurator`はデフォルトで設定の競合を検出し、他のパッケージやモジュールからの設定を必須に含めることができます。また、デフォルトでは、2つの別々のフェーズで構成を実行します。これにより、状況によっては相対的な構成ステートメントの順序を無視することができます。

競合検出

ここでは、最も単純なapp: `Pyramid`アプリケーションのおなじみの例を挙げます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
    return Response('Hello world!')

if __name__ == '__main__':
    config = Configurator()
    config.add_view(hello_world)
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

このアプリケーションを起動すると、すべてがOKになります。しかし、同じ:term: `predicate`引数を既に設定したものと同じ設定で別のビューを設定に追加しようとするとどうなりますか?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
    return Response('Hello world!')

def goodbye_world(request):
    return Response('Goodbye world!')

if __name__ == '__main__':
    config = Configurator()

    config.add_view(hello_world, name='hello')

    # conflicting view configuration
    config.add_view(goodbye_world, name='hello')

    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

アプリケーションに2つの競合するビュー構成ステートメントがあります。もう一度やり直すと、それは始まりません。代わりに、次のような終わりのトレースバックを受け取ります:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Traceback (most recent call last):
  File "app.py", line 12, in <module>
    app = config.make_wsgi_app()
  File "pyramid/config.py", line 839, in make_wsgi_app
    self.commit()
  File "pyramid/pyramid/config.py", line 473, in commit
    self._ctx.execute_actions()
  ... more code ...
pyramid.exceptions.ConfigurationConflictError:
        Conflicting configuration actions
  For: ('view', None, '', None, <InterfaceClass pyramid.interfaces.IView>,
        None, None, None, None, None, False, None, None, None)
  Line 14 of file app.py in <module>: 'config.add_view(hello_world)'
  Line 17 of file app.py in <module>: 'config.add_view(goodbye_world)'

このトレースバックは私たちに伝えようとしています:

  • 一連のビュー設定ステートメント( `` For: ``行)の情報が矛盾しています。
  • `` for: `` app.py`の14行目の `` For: ``の行の下に表示される `` config.add_view(hello_world。 &#39;hello&#39;) ``と `` config.add_view (goodbye_world、 &#39;hello&#39;) `` app.py`の17行目にあります。

これらの2つの構成ステートメントは、両方のビュー構成のset:term: predicate`値がまったく同じであることをシステムに伝えようとしたため、矛盾しています。 ` hello_world``と `` goodbye_world``の両方のビューは、同じ状況下で応答するように設定されています。この状況は、 `` name = ``述語で表される:term: view name`は `hello``です。

これはあいまいさをもたらす:app: `Pyramid`は解決できません。状況が報告されないようにするのではなく、Pyramidはデフォルトで:exc: `ConfigurationConflictError`エラーを発生させ、アプリケーションの実行を防ぎます。

競合の検出は、どのような種類の設定でも起こります:a:term: `scan`の実行の結果生じる必須の設定または設定です。

競合の手動解決

競合を手動で解決するには、:meth: `pyramid.config.Configurator.commit`を戦略的に使用するか、または「自動コミット」コンフィギュレータを使用して、競合しないように登録を変更する方法があります。

良い行い

競合を解決する最も正しい方法は、必要な作業を行うことです:競合する構成ステートメントを持たないように構成コードを変更します。これがどのように行われるかの詳細は、アプリケーションによって行われた構成ステートメントに完全に依存します。 :exc: `ConfigurationConflictError`で提供されている詳細を使用して問題の衝突を追跡し、それに応じて設定コードを変更します。

既存のアプリケーションを拡張しようとする際に競合が発生し、そのアプリケーションが次のような構成を実行する機能を持っている場合は、

1
2
def add_routes(config):
    config.add_route(...)

この関数を `` config``を引数として直接呼び出さないでください。代わりに、:meth: `pyramid.config.Configurator.include`を使用してください:

1
config.include(add_routes)

関数を直接呼び出す代わりに:meth: `〜pyramid.config.Configurator.include`を使うと、呼び出したコードで定義した設定ステートメントが、インクルードされた関数のものよりも優先され、自動的に競合解消が行われます。

参考

ref: automatic_conflict_resolution`と:ref: including_configuration`も参照してください。

`` config.commit() ``を使う

コンフィグレーションコール間で:meth: `〜pyramid.config.Configurator.commit`メソッドを使って手動でコンフィグレーションをコミットすることができます。たとえば、以前に &quot;commit&quot;を追加した結果、アプリケーションで競合が発生しないようにします。競合を生成するアプリケーションは次のとおりです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
    return Response('Hello world!')

def goodbye_world(request):
    return Response('Goodbye world!')

if __name__ == '__main__':
    config = Configurator()

    config.add_view(hello_world, name='hello')

    # conflicting view configuration
    config.add_view(goodbye_world, name='hello')

    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

2つの `` add_view``呼び出しが衝突するのを防ぐには:meth: `〜pyramid.config.Configurator.commit`を呼び出します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
    return Response('Hello world!')

def goodbye_world(request):
    return Response('Goodbye world!')

if __name__ == '__main__':
    config = Configurator()

    config.add_view(hello_world, name='hello')

    config.commit() # commit any pending configuration actions

    # no-longer-conflicting view configuration
    config.add_view(goodbye_world, name='hello')

    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()

上記の例では、2つの `` add_view``呼び出しの間に:meth: `〜pyramid.config.Configurator.commit`を呼び出しました。 :meth: `〜pyramid.config.Configurator.commit`は保留中の設定文を実行します。

呼び出し:meth: `〜pyramid.config.Configurator.commit`はいつでも安全です。すべての保留中の設定アクションを実行し、設定アクションリスト&quot;クリーン&quot;を残します。

Note that commit() has no effect when you're using an autocommitting configurator (see 自動コミット・コンフィグレータの使用).

自動コミット・コンフィグレータの使用

重いハンマーを使用して、コンフリクト検出を回避することもできます。コンストラクタコンストラクタのパラメータは `` autocommit = True``です。例えば:

1
2
3
4
from pyramid.config import Configurator

if __name__ == '__main__':
    config = Configurator(autocommit=True)

Configuratorに渡される `` autocommit``パラメータが `` True``の場合、競合検出(:::twophase_config)が無効になります。構成文は直ちに実行され、後続の文は先行する文を上書きします。

:meth: 〜pyramid.config.Configurator.commit`は autocommit``が `True``のときは効果がありません。

単体テストを実行するコードでコンフィグレータを使用する場合は、通常、コンフリクトの検出やテストコードの2段階コンフィグレーションに関心がないため、自動コミットコンフィグレータを使用することをお勧めします。

自動競合解決

あなたのコードが:meth: `〜pyramid.config.Configurator.include`メソッドを使用して外部設定を組み込む場合、いくつかの競合が自動的に解決されます。 &quot;include &quot;の結果として構成された構成ステートメントは、&quot;include &quot;メソッドの呼び出し元で発生する構成ステートメントによってオーバーライドされます。

自動競合解決は、この目標をサポートします。 Pyramidアプリケーションを再利用したいときに、コードを外部からハッキングせずにこのアプリケーションの設定をカスタマイズしたい場合は、パッケージの設定関数を &quot;インクルード&quot;して、その一部だけを上書きすることができますインクルードを行うコード内の構成ステートメント含まれているコード内の構成ステートメントが呼び出しコードに移動した場合に競合する場合でも、インクルードするコード内の構成ステートメントによって競合は発生しません。

競合検出を提供する方法

競合検出を提供するコンフィギュレータのメソッドは次のとおりです。

:meth: 〜pyramid.config.Configurator.add_view、:meth:〜pyramid.config.Configurator.add_route、:meth: 〜pyramid.config.Configurator.add_renderer、:meth:〜pyramid.config .Met: `〜pyramid.config.Configurator.set_request_property::meth:〜pyramid.config.Configurator.set_session_factory、:meth: 〜pyramid.config.Configurator.set_request_property、:meth :〜pyramid.config.Configurator.set_root_factory`、:meth: 〜pyramid.config.Configurator.set_view_mapper、:meth:〜pyramid.config.Configurator.set_authentication_policy、:meth: 〜pyramid.config.Configurator .set_authorization_policy、:meth: 〜pyramid.config.Configurator.add_traverser、:meth:〜pyramid.config.Configurator.add_policy、:meth: 〜pyramid.config.Configurator.add_traverser、:meth:〜pyramid.config.Configurator.set_default_permission、 〜pyramid.config.Configurator.add_resource_url_adapter`、および:meth: 〜pyramid.config.Configurator.add_response_adapter

:meth: 〜pyramid.config.Configurator.add_static_view`は、コンフリクトを認識した add_route``と `add_view``メソッドの観点から実装されているので、間接的にコンフリクト検出を提供します。

外部ソースからの設定を含む

アプリケーションプログラマの中には、構成ステートメントを再利用して上書きする方法で構成コードを考慮するものもあります。たとえば、そのような開発者は、アプリケーションにルートを追加するために使用される関数を除外することができます。

1
2
def add_routes(config):
    config.add_route(...)

この関数を `` config``を引数として直接呼び出すのではなく、代わりに:meth: pyramid.config.Configurator.include

1
config.include(add_routes)

関数を直接呼び出すのではなく、 `` include``を使うと:ref: `automatic_conflict_resolution`が動作するようになります。

:meth: 〜pyramid.config.Configurator.include`は:term: module`を引数として受け入れることもできます:

1
2
3
import myapp

config.include(myapp)

これが正しく動作するためには、 `` myapp``モジュールは特別な名前 `` includeme`を持つ呼び出し可能なものを含んでいなければなりません(上記の `` add_routes``呼び出しのように)

:meth: 〜pyramid.config.Configurator.include`は、:term: dotted Python name`を関数またはモジュールに受け入れることもできます。

注釈

:meth: 〜pyramid.config.Configurator.include`メソッドの宣言的な代替方法については:ref: the_include_tag`を参照してください。

二相構成

非自動コミッティング:用語:Configuratorを使用して構成(デフォルト)を行うと、構成の実行は2つのフェーズで行われます。最初のフェーズでは、 &quot;eager&quot;構成アクション(レンダラーの登録など、他のすべてのアクションの前に行わなければならないアクション)が実行され、熱心なアクションの結果に依存する各アクションについて* discriminators *が計算されます。第2フェーズでは、すべてのアクションのディスクリミネータが競合検出を行うために比較されます。

このため、内部順序制約がない構成メソッドの場合、構成メソッド呼び出しの実行順序は重要ではありません。たとえば、非オートコミッティングコンフィギュレータが使用されている場合、:meth: 〜pyramid.config.Configurator.add_view`と:meth:〜pyramid.config.Configurator.add_renderer`の相対的な順序は重要ではありません。このコードスニペット:

1
2
config.add_view('some.view', renderer='path_to_custom/renderer.rn')
config.add_renderer('.rn', SomeCustomRendererFactory)

同じ結果があります:

1
2
config.add_renderer('.rn', SomeCustomRendererFactory)
config.add_view('some.view', renderer='path_to_custom/renderer.rn')

ビューステートメントは、カスタムレンダラーの登録に依存しますが、2フェーズ構成のため、構成ステートメントの発行順序は重要ではありません。 `` add_view``の後に `` add_renderer``が呼び出されても、 `` add_view``は `` .rn``レンダラーを見つけることができます。

The same is untrue when you use an autocommitting configurator (see 自動コミット・コンフィグレータの使用). When an autocommitting configurator is used, two-phase configuration is disabled, and configuration statements must be ordered in dependency order.

:meth: `〜pyramid.config.Configurator.add_route`のような設定メソッドには、内部的な順序制約があります。このような順序制約は、2フェーズ構成では解決されません。経路は構成実行順序で追加されます。

詳しくは

詳細は、次の記事を参照してください:ref: `高度な構成の戦術の旋風のツアー<cookbook:whirlwind-adv-conf> `ピラミッドコミュニティクックブックで。