(機械翻訳) 高度な設定¶
アプリケーションの拡張性をサポートするため、: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。 'hello') ``と `` config.add_view (goodbye_world、 'hello') `` 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`メソッドを使って手動でコンフィグレーションをコミットすることができます。たとえば、以前に "commit"を追加した結果、アプリケーションで競合が発生しないようにします。競合を生成するアプリケーションは次のとおりです。
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`はいつでも安全です。すべての保留中の設定アクションを実行し、設定アクションリスト"クリーン"を残します。
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`メソッドを使用して外部設定を組み込む場合、いくつかの競合が自動的に解決されます。 "include "の結果として構成された構成ステートメントは、"include "メソッドの呼び出し元で発生する構成ステートメントによってオーバーライドされます。
自動競合解決は、この目標をサポートします。 Pyramidアプリケーションを再利用したいときに、コードを外部からハッキングせずにこのアプリケーションの設定をカスタマイズしたい場合は、パッケージの設定関数を "インクルード"して、その一部だけを上書きすることができますインクルードを行うコード内の構成ステートメント含まれているコード内の構成ステートメントが呼び出しコードに移動した場合に競合する場合でも、インクルードするコード内の構成ステートメントによって競合は発生しません。
競合検出を提供する方法¶
競合検出を提供するコンフィギュレータのメソッドは次のとおりです。
: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つのフェーズで行われます。最初のフェーズでは、 "eager"構成アクション(レンダラーの登録など、他のすべてのアクションの前に行わなければならないアクション)が実行され、熱心なアクションの結果に依存する各アクションについて* 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フェーズ構成では解決されません。経路は構成実行順序で追加されます。