<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:1.2em 0px!important">Hi Christoph,</p>
<p style="margin:1.2em 0px!important">On Wed, Dec 7, 2016 at 11:51 AM Christoph Deil <a href="http://mailto:deil.christoph@googlemail.com">deil.christoph@googlemail.com</a> wrote:</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg">Are there any real pros and cons for the two options? Or are both equally powerful and it’s a matter of taste?<br></div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">IMHO it seems to be a matter of taste. The <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">requires_dependency</code> function still requires you to explicitly import the module inside the test file to obtain the module object:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-python" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;background:rgb(35,36,31);color:rgb(248,248,242)"><span class="hljs-keyword" style="color:rgb(249,38,114)">from</span> gammapy.utils.testing <span class="hljs-keyword" style="color:rgb(249,38,114)">import</span> requires_dependency

<span class="hljs-decorator" style="color:rgb(117,113,94)">@requires_dependency(&#39;scipy&#39;)</span>
<span class="hljs-function" style="color:rgb(249,38,114)"><span class="hljs-keyword" style="color:rgb(249,38,114);color:rgb(102,217,239)">def</span> <span class="hljs-title" style="color:rgb(166,226,46)">test_using_scipy</span><span class="hljs-params" style="color:rgb(248,248,242)">()</span>:</span>
    <span class="hljs-keyword" style="color:rgb(249,38,114)">import</span> scipy
</code></pre>
<p style="margin:1.2em 0px!important">Compared with <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pytest.importorskip</code>:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-python" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;background:rgb(35,36,31);color:rgb(248,248,242)"><span class="hljs-keyword" style="color:rgb(249,38,114)">import</span> pytest

<span class="hljs-function" style="color:rgb(249,38,114)"><span class="hljs-keyword" style="color:rgb(249,38,114);color:rgb(102,217,239)">def</span> <span class="hljs-title" style="color:rgb(166,226,46)">test_using_scipy</span><span class="hljs-params" style="color:rgb(248,248,242)">()</span>:</span>
    scipy = pytest.importorskip(<span class="hljs-string" style="color:rgb(230,219,116)">&#39;scipy&#39;</span>)
</code></pre>
<p style="margin:1.2em 0px!important">So I think <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">requires_dependency</code> has the following cons:</p>
<ul style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px">It might be more explicit, since <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pytest.importorskip</code> might be used deep inside the test function and easy to miss, while the decorator stands out;</li>
<li style="margin:0.5em 0px">It is more friendly to IDEs like PyCharm/PyDev, with code-completion, documentation, etc.</li>
</ul>
<p style="margin:1.2em 0px!important">The only cons I can think of is that it requires one extra line and the extra import (since it is common for tests to import <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pytest</code> for other reasons as well).</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg">Do you think such a decorator would be appropriate for a pytest plugin?<br></div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">If others find it useful, I don’t see why not. :)</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"></div><div class="gmail_msg">Or even to be proposed as a convenience for pytest core?</div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">I personally would be -0 on this because I feel it seems too similar to using <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pytest.importorskip</code> method so I would avoid having two ways of doing the same thing. On the other hand, the implementation would be really simple so it wouldn’t be a maintenance burden if others really like it.</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg">Or would you just recommend we implement what we want in our own `utils.py` instead of trying to generalise a solution for this?</div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">I think it is really commendable of you to try to provide a general solution to the community, so please don’t get discouraged by my <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">-0</code>. And since the implementation is simple and <a href="https://github.com/pytest-dev/cookiecutter-pytest-plugin">cookiecutter-pytest-plugin</a> makes creating plugins a snap, you should definitely go with it if you really prefer the decoration method.</p>
<p style="margin:1.2em 0px!important">Cheers,<br>Bruno.</p>
<div title="MDH:SGkgQ2hyaXN0b3BoLDxkaXY+PGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXYgY2xhc3M9Imdt
YWlsX3F1b3RlIj48ZGl2IGRpcj0ibHRyIj5PbiBXZWQsIERlYyA3LCAyMDE2IGF0IDExOjUxIEFN
IENocmlzdG9waCBEZWlsICZsdDtkZWlsLmNocmlzdG9waEBnb29nbGVtYWlsLmNvbSZndDsgd3Jv
dGU6PGJyPjwvZGl2PjxibG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdp
bjowIDAgMCAuOGV4O2JvcmRlci1sZWZ0OjFweCAjY2NjIHNvbGlkO3BhZGRpbmctbGVmdDoxZXg7
Ij48ZGl2IHN0eWxlPSJ3b3JkLXdyYXA6YnJlYWstd29yZCIgY2xhc3M9ImdtYWlsX21zZyI+PGRp
diBjbGFzcz0iZ21haWxfbXNnIj5BcmUgdGhlcmUgYW55IHJlYWwgcHJvcyBhbmQgY29ucyBmb3Ig
dGhlIHR3byBvcHRpb25zPyBPciBhcmUgYm90aCBlcXVhbGx5IHBvd2VyZnVsIGFuZCBpdOKAmXMg
YSBtYXR0ZXIgb2YgdGFzdGU/PGJyPjwvZGl2PjwvZGl2PjwvYmxvY2txdW90ZT48ZGl2Pjxicj48
L2Rpdj48ZGl2PklNSE8gaXQgc2VlbXMgdG8gYmUgYSBtYXR0ZXIgb2YgdGFzdGUuIFRoZSBgcmVx
dWlyZXNfZGVwZW5kZW5jeWAgZnVuY3Rpb24gc3RpbGwgcmVxdWlyZXMgeW91IHRvIGV4cGxpY2l0
bHkgaW1wb3J0IHRoZSBtb2R1bGUgaW5zaWRlIHRoZSB0ZXN0IGZpbGUgdG8gb2J0YWluIHRoZSBt
b2R1bGUgb2JqZWN0OjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+YGBgcHl0aG9uPC9kaXY+PGRp
dj48ZGl2PmZyb20gZ2FtbWFweS51dGlscy50ZXN0aW5nIGltcG9ydCByZXF1aXJlc19kZXBlbmRl
bmN5PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5AcmVxdWlyZXNfZGVwZW5kZW5jeSgnc2NpcHkn
KTwvZGl2PjxkaXY+ZGVmIHRlc3RfdXNpbmdfc2NpcHkoKTo8L2Rpdj48ZGl2PiZuYnNwOyAmbmJz
cDsgaW1wb3J0IHNjaXB5PC9kaXY+PC9kaXY+PGRpdj5gYGA8L2Rpdj48ZGl2Pjxicj48L2Rpdj48
ZGl2PkNvbXBhcmVkIHdpdGggYHB5dGVzdC5pbXBvcnRvcnNraXBgOjwvZGl2PjxkaXY+PGJyPjwv
ZGl2PjxkaXY+YGBgcHl0aG9uPC9kaXY+PGRpdj48ZGl2PmltcG9ydCBweXRlc3Q8L2Rpdj48ZGl2
Pjxicj48L2Rpdj48ZGl2PmRlZiB0ZXN0X3VzaW5nX3NjaXB5KCk6PC9kaXY+PGRpdj4mbmJzcDsg
Jm5ic3A7IHNjaXB5ID0gcHl0ZXN0LmltcG9ydG9yc2tpcCgnc2NpcHknKTwvZGl2PjwvZGl2Pjxk
aXY+YGBgPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5TbyBJIHRoaW5rIGByZXF1aXJlc19kZXBl
bmRlbmN5YCBoYXMgdGhlIGZvbGxvd2luZyBjb25zOjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+
KiBJdCBtaWdodCBiZSBtb3JlIGV4cGxpY2l0LCBzaW5jZSBgcHl0ZXN0LmltcG9ydG9yc2tpcGAg
bWlnaHQgYmUgdXNlZCBkZWVwIGluc2lkZSB0aGUgdGVzdCBmdW5jdGlvbiBhbmQgZWFzeSB0byBt
aXNzLCB3aGlsZSB0aGUgZGVjb3JhdG9yIHN0YW5kcyBvdXQ7PC9kaXY+PGRpdj4qIEl0IGlzIG1v
cmUgZnJpZW5kbHkgdG8gSURFcyBsaWtlIFB5Q2hhcm0vUHlEZXYsIHdpdGggY29kZS1jb21wbGV0
aW9uLCBkb2N1bWVudGF0aW9uLCBldGMuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5UaGUgb25s
eSBjb25zIEkgY2FuIHRoaW5rIG9mIGlzIHRoYXQgaXQgcmVxdWlyZXMgb25lIGV4dHJhIGxpbmUg
YW5kIHRoZSBleHRyYSBpbXBvcnQgKHNpbmNlIGl0IGlzIGNvbW1vbiBmb3IgdGVzdHMgdG8gaW1w
b3J0IGBweXRlc3RgIGZvciBvdGhlciByZWFzb25zIGFzIHdlbGwpLjwvZGl2PjxkaXY+PGJyPjwv
ZGl2PjxibG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjowIDAgMCAu
OGV4O2JvcmRlci1sZWZ0OjFweCAjY2NjIHNvbGlkO3BhZGRpbmctbGVmdDoxZXg7Ij48ZGl2IHN0
eWxlPSJ3b3JkLXdyYXA6YnJlYWstd29yZCIgY2xhc3M9ImdtYWlsX21zZyI+PGRpdiBjbGFzcz0i
Z21haWxfbXNnIj5EbyB5b3UgdGhpbmsgc3VjaCBhIGRlY29yYXRvciB3b3VsZCBiZSBhcHByb3By
aWF0ZSBmb3IgYSBweXRlc3QgcGx1Z2luPzxicj48L2Rpdj48L2Rpdj48L2Jsb2NrcXVvdGU+PGRp
dj48YnI+PC9kaXY+PGRpdj5JZiBvdGhlcnMgZmluZCBpdCB1c2VmdWwsIEkgZG9uJ3Qgc2VlIHdo
eSBub3QuIDopPC9kaXY+PGRpdj4mbmJzcDs8L2Rpdj48YmxvY2txdW90ZSBjbGFzcz0iZ21haWxf
cXVvdGUiIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXItbGVmdDoxcHggI2NjYyBzb2xp
ZDtwYWRkaW5nLWxlZnQ6MWV4OyI+PGRpdiBzdHlsZT0id29yZC13cmFwOmJyZWFrLXdvcmQiIGNs
YXNzPSJnbWFpbF9tc2ciPjxkaXYgY2xhc3M9ImdtYWlsX21zZyI+PC9kaXY+PGRpdiBjbGFzcz0i
Z21haWxfbXNnIj5PciBldmVuIHRvIGJlIHByb3Bvc2VkIGFzIGEgY29udmVuaWVuY2UgZm9yIHB5
dGVzdCBjb3JlPzwvZGl2PjwvZGl2PjwvYmxvY2txdW90ZT48ZGl2Pjxicj48L2Rpdj48ZGl2Pkkg
cGVyc29uYWxseSB3b3VsZCBiZSAtMCBvbiB0aGlzIGJlY2F1c2UgSSBmZWVsIGl0IHNlZW1zIHRv
byBzaW1pbGFyIHRvIHVzaW5nIGBweXRlc3QuaW1wb3J0b3Jza2lwYCBtZXRob2Qgc28gSSB3b3Vs
ZCBhdm9pZCBoYXZpbmcgdHdvIHdheXMgb2YgZG9pbmcgdGhlIHNhbWUgdGhpbmcuIE9uIHRoZSBv
dGhlciBoYW5kLCB0aGUgaW1wbGVtZW50YXRpb24gd291bGQgYmUgcmVhbGx5IHNpbXBsZSBzbyBp
dCB3b3VsZG4ndCBiZSBhIG1haW50ZW5hbmNlIGJ1cmRlbiBpZiBvdGhlcnMgcmVhbGx5IGxpa2Ug
aXQuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGJsb2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1b3RlIiBz
dHlsZT0ibWFyZ2luOjAgMCAwIC44ZXg7Ym9yZGVyLWxlZnQ6MXB4ICNjY2Mgc29saWQ7cGFkZGlu
Zy1sZWZ0OjFleDsiPjxkaXYgc3R5bGU9IndvcmQtd3JhcDpicmVhay13b3JkIiBjbGFzcz0iZ21h
aWxfbXNnIj48ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPk9yIHdvdWxkIHlvdSBqdXN0IHJlY29tbWVu
ZCB3ZSBpbXBsZW1lbnQgd2hhdCB3ZSB3YW50IGluIG91ciBvd24gYHV0aWxzLnB5YCBpbnN0ZWFk
IG9mIHRyeWluZyB0byBnZW5lcmFsaXNlIGEgc29sdXRpb24gZm9yIHRoaXM/PC9kaXY+PC9kaXY+
PC9ibG9ja3F1b3RlPjxkaXY+PGJyPjwvZGl2PjxkaXY+SSB0aGluayBpdCBpcyByZWFsbHkgY29t
bWVuZGFibGUgb2YgeW91IHRvIHRyeSB0byBwcm92aWRlIGEgZ2VuZXJhbCBzb2x1dGlvbiB0byB0
aGUgY29tbXVuaXR5LCBzbyBwbGVhc2UgZG9uJ3QgZ2V0IGRpc2NvdXJhZ2VkIGJ5IG15IGAtMGAu
IEFuZCBzaW5jZSB0aGUgaW1wbGVtZW50YXRpb24gaXMgc2ltcGxlIGFuZCBbY29va2llY3V0dGVy
LXB5dGVzdC1wbHVnaW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9weXRlc3QtZGV2L2Nvb2tpZWN1dHRl
ci1weXRlc3QtcGx1Z2luKSBtYWtlcyBjcmVhdGluZyBwbHVnaW5zIGEgc25hcCwgeW91IHNob3Vs
ZCBkZWZpbml0ZWx5IGdvIHdpdGggaXQgaWYgeW91IHJlYWxseSBwcmVmZXIgdGhlIGRlY29yYXRp
b24gbWV0aG9kLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+Q2hlZXJzLDwvZGl2PjxkaXY+QnJ1
bm8uPC9kaXY+PC9kaXY+" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></div></div>