1. ホーム
  2. python

[解決済み] Pythonのデコレーターが関数をラップする前にパッチを当てることはできますか?

2023-01-10 11:23:16

質問

Pythonの助けを借りてテストしているデコレータを持つ関数があります。 モック ライブラリの助けを借りてテストしようとしています。私は mock.patch を使用して、実際のデコレータを単に関数を呼び出すだけのモック「バイパス」デコレータに置き換えます。

わからないのは、本物のデコレータが関数をラップする前にパッチを適用する方法です。パッチターゲットにいくつかの異なるバリエーションを試し、パッチと import ステートメントを並べ替えてみましたが、成功しませんでした。何かアイデアはありますか?

どのように解決するのですか?

デコレータは、関数定義時に適用されます。ほとんどの関数では、これはモジュールがロードされたときです。(他の関数で定義されている関数は、その関数が呼ばれるたびにデコレータが適用されます)。

ですから、もしあなたがデコレーターを猿真似したいのであれば、 必要なことは

  1. それを含むモジュールをインポートする
  2. モックデコレータ関数を定義する
  3. 設定 など module.decorator = mymockdecorator
  4. デコレータを使用するモジュールをインポートするか、独自のモジュールで使用します。

デコレータを含むモジュールに、それを使用する関数も含まれている場合、それらはあなたが見ることができる時点で既に装飾されており、あなたはおそらくS.O.L.でしょう。

最初にこれを書いてからPythonの変更を反映させるために編集しました。もしデコレータが functools.wraps() を使っていて、Python のバージョンが十分に新しい場合、元の関数を掘り出すことができるかもしれません。 __wrapped__ 属性を使って元の関数を見つけ出し、それを再装飾することができるかもしれません。しかし、これは決して保証されたものではなく、置き換えたいデコレータが適用されている唯一のデコレータであるとは限りません。