<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 Thu, Dec 8, 2016 at 6:19 AM Christoph Deil <a href="http://mailto:[deil.christoph@googlemail.com](mailto:deil.christoph@googlemail.com)">[deil.christoph@googlemail.com](mailto: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 gmail_msg" 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 class="gmail_msg">Just to clarify: the way we handle optional dependencies in the (non-test) code is to put them as delayed imports only inside the function or method where they are used.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">E.g. we have classes that have much functionality for computation, and then one plot method and only that requires “import matplotlib”, because that import is in the plot method.</div><div class="gmail_msg"><br class="gmail_msg"></div>So the extra “import scipy” line in the test code example you give above is never there in our tests.</div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">I see, thanks for the clarification.</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote gmail_msg" 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 class="gmail_msg">One basic question I still have is what the advantage is of having this as a Pytest plugin, instead of just a single-file .py module from which people can import the requires_dependency decorator? Would this allow me to expose the decorator in the top-level pytest or some other namespace? Is this a good idea?</div></div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">You can use the <a href="http://doc.pytest.org/en/latest/writing_plugins.html?highlight=pytest_namespace#_pytest.hookspec.pytest_namespace">pytest_namespace</a> hook to expose decorator through <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>‘s own namespace so users can write this:</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-decorator" style="color:rgb(117,113,94)">@pytest.requires_dependency(‘scipy&gt;=0.15, matplotlib’)</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>
</code></pre>
<p style="margin:1.2em 0px!important">That’s the same mechanism pytest itself uses to expose its own builtin functionality like <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.mark</code> for example.</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote gmail_msg" 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 class="gmail_msg"><div class="gmail_msg">Are there one or a few examples of plugins that I could look at before getting started that are similar to what I’m trying to do?</div></div></div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">Can’t think of one out of the top of my head right now, sorry. </p>
<p style="margin:1.2em 0px!important">If you go ahead and implement a plugin, please make sure to announce here in the list for those interested. :) </p>
<p style="margin:1.2em 0px!important">Cheers,<br>Bruno.</p>
<div title="MDH:PGRpdiBkaXI9Imx0ciIgY2xhc3M9ImdtYWlsX21zZyI+SGkgQ2hyaXN0b3BoLDxiciBjbGFzcz0i
Z21haWxfbXNnIj48YnIgY2xhc3M9ImdtYWlsX21zZyI+PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUg
Z21haWxfbXNnIj48L2Rpdj48L2Rpdj48ZGl2IGRpcj0ibHRyIiBjbGFzcz0iZ21haWxfbXNnIj48
ZGl2IGNsYXNzPSJnbWFpbF9xdW90ZSBnbWFpbF9tc2ciPjxkaXYgZGlyPSJsdHIiIGNsYXNzPSJn
bWFpbF9tc2ciPk9uIFRodSwgRGVjIDgsIDIwMTYgYXQgNjoxOSBBTSBDaHJpc3RvcGggRGVpbCAm
bHQ7PGEgaHJlZj0ibWFpbHRvOmRlaWwuY2hyaXN0b3BoQGdvb2dsZW1haWwuY29tIiBjbGFzcz0i
Z21haWxfbXNnIiB0YXJnZXQ9Il9ibGFuayI+ZGVpbC5jaHJpc3RvcGhAZ29vZ2xlbWFpbC5jb208
L2E+PHdicj4mZ3Q7IHdyb3RlOjwvZGl2PjxibG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSBn
bWFpbF9tc2ciIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXItbGVmdDoxcHggI2NjYyBz
b2xpZDtwYWRkaW5nLWxlZnQ6MWV4Ij48ZGl2IHN0eWxlPSJ3b3JkLXdyYXA6YnJlYWstd29yZCIg
Y2xhc3M9ImdtYWlsX21zZyI+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj48ZGl2IGNsYXNzPSJnbWFp
bF9tc2ciPkp1c3QgdG8gY2xhcmlmeTogdGhlIHdheSB3ZSBoYW5kbGUgb3B0aW9uYWwgZGVwZW5k
ZW5jaWVzIGluIHRoZSAobm9uLXRlc3QpIGNvZGUgaXMgdG8gcHV0IHRoZW0gYXMgZGVsYXllZCBp
bXBvcnRzIG9ubHkgaW5zaWRlIHRoZSBmdW5jdGlvbiBvciBtZXRob2Qgd2hlcmUgdGhleSBhcmUg
dXNlZC48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPjxiciBjbGFzcz0iZ21haWxfbXNnIj48
L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPkUuZy4gd2UgaGF2ZSBjbGFzc2VzIHRoYXQgaGF2
ZSBtdWNoIGZ1bmN0aW9uYWxpdHkgZm9yIGNvbXB1dGF0aW9uLCBhbmQgdGhlbiBvbmUgcGxvdCBt
ZXRob2QgYW5kIG9ubHkgdGhhdCByZXF1aXJlcyDigJxpbXBvcnQgbWF0cGxvdGxpYuKAnSwgYmVj
YXVzZSB0aGF0IGltcG9ydCBpcyBpbiB0aGUgcGxvdCBtZXRob2QuPC9kaXY+PGRpdiBjbGFzcz0i
Z21haWxfbXNnIj48YnIgY2xhc3M9ImdtYWlsX21zZyI+PC9kaXY+U28gdGhlIGV4dHJhIOKAnGlt
cG9ydCBzY2lweeKAnSBsaW5lIGluIHRoZSB0ZXN0IGNvZGUgZXhhbXBsZSB5b3UgZ2l2ZSBhYm92
ZSBpcyBuZXZlciB0aGVyZSBpbiBvdXIgdGVzdHMuPC9kaXY+PC9kaXY+PC9ibG9ja3F1b3RlPjxk
aXYgY2xhc3M9ImdtYWlsX21zZyI+PGJyIGNsYXNzPSJnbWFpbF9tc2ciPjwvZGl2PjwvZGl2Pjwv
ZGl2PjxkaXYgZGlyPSJsdHIiIGNsYXNzPSJnbWFpbF9tc2ciPjxkaXYgY2xhc3M9ImdtYWlsX3F1
b3RlIGdtYWlsX21zZyI+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj5JIHNlZSwgdGhhbmtzIGZvciB0
aGUgY2xhcmlmaWNhdGlvbi48L2Rpdj48L2Rpdj48L2Rpdj48ZGl2IGRpcj0ibHRyIiBjbGFzcz0i
Z21haWxfbXNnIj48ZGl2IGNsYXNzPSJnbWFpbF9xdW90ZSBnbWFpbF9tc2ciPjxkaXYgY2xhc3M9
ImdtYWlsX21zZyI+PGJyIGNsYXNzPSJnbWFpbF9tc2ciPjwvZGl2PjxibG9ja3F1b3RlIGNsYXNz
PSJnbWFpbF9xdW90ZSBnbWFpbF9tc2ciIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXIt
bGVmdDoxcHggI2NjYyBzb2xpZDtwYWRkaW5nLWxlZnQ6MWV4Ij48ZGl2IHN0eWxlPSJ3b3JkLXdy
YXA6YnJlYWstd29yZCIgY2xhc3M9ImdtYWlsX21zZyI+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj48
ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPk9uZSBiYXNpYyBxdWVzdGlvbiBJIHN0aWxsIGhhdmUgaXMg
d2hhdCB0aGUgYWR2YW50YWdlIGlzIG9mIGhhdmluZyB0aGlzIGFzIGEgUHl0ZXN0IHBsdWdpbiwg
aW5zdGVhZCBvZiBqdXN0IGEgc2luZ2xlLWZpbGUgLnB5IG1vZHVsZSBmcm9tIHdoaWNoIHBlb3Bs
ZSBjYW4gaW1wb3J0IHRoZSByZXF1aXJlc19kZXBlbmRlbmN5IGRlY29yYXRvcj8gV291bGQgdGhp
cyBhbGxvdyBtZSB0byBleHBvc2UgdGhlIGRlY29yYXRvciBpbiB0aGUgdG9wLWxldmVsIHB5dGVz
dCBvciBzb21lIG90aGVyIG5hbWVzcGFjZT8gSXMgdGhpcyBhIGdvb2QgaWRlYT88L2Rpdj48L2Rp
dj48L2Rpdj48L2Jsb2NrcXVvdGU+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj48YnIgY2xhc3M9Imdt
YWlsX21zZyI+PC9kaXY+PC9kaXY+PC9kaXY+PGRpdiBkaXI9Imx0ciIgY2xhc3M9ImdtYWlsX21z
ZyI+PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUgZ21haWxfbXNnIj48ZGl2IGNsYXNzPSJnbWFpbF9t
c2ciPllvdSBjYW4gdXNlIHRoZSBbcHl0ZXN0X25hbWVzcGFjZV0oPGEgaHJlZj0iaHR0cDovL2Rv
Yy5weXRlc3Qub3JnL2VuL2xhdGVzdC93cml0aW5nX3BsdWdpbnMuaHRtbD9oaWdobGlnaHQ9cHl0
ZXN0X25hbWVzcGFjZSNfcHl0ZXN0Lmhvb2tzcGVjLnB5dGVzdF9uYW1lc3BhY2UiIGNsYXNzPSJn
bWFpbF9tc2ciIHRhcmdldD0iX2JsYW5rIiBkYXRhLXNhZmVyZWRpcmVjdHVybD0iaHR0cHM6Ly93
d3cuZ29vZ2xlLmNvbS91cmw/cT1odHRwOi8vZG9jLnB5dGVzdC5vcmcvZW4vbGF0ZXN0L3dyaXRp
bmdfcGx1Z2lucy5odG1sP2hpZ2hsaWdodCUzRHB5dGVzdF9uYW1lc3BhY2UlMjNfcHl0ZXN0Lmhv
b2tzcGVjLnB5dGVzdF9uYW1lc3BhY2UmYW1wO3NvdXJjZT1nbWFpbCZhbXA7dXN0PTE0ODEyODQ1
MDM4MDMwMDAmYW1wO3VzZz1BRlFqQ05GZnd0cU1Sc2lIajAxSFEyb0F5enZUdTlFMEVRIj5odHRw
Oi8vZG9jLjx3YnI+cHl0ZXN0Lm9yZy9lbi9sYXRlc3Qvd3JpdGluZ188d2JyPnBsdWdpbnMuaHRt
bD9oaWdobGlnaHQ9cHl0ZXN0Xzx3YnI+bmFtZXNwYWNlI19weXRlc3QuaG9va3NwZWMuPHdicj5w
eXRlc3RfbmFtZXNwYWNlPC9hPikgaG9vayB0byBleHBvc2UgZGVjb3JhdG9yIHRocm91Z2ggYHB5
dGVzdGAncyBvd24gbmFtZXNwYWNlIHNvIHVzZXJzIGNhbiB3cml0ZSB0aGlzOjwvZGl2PjxkaXYg
Y2xhc3M9ImdtYWlsX21zZyI+PGJyIGNsYXNzPSJnbWFpbF9tc2ciPjwvZGl2PjxkaXYgY2xhc3M9
ImdtYWlsX21zZyI+YGBgcHl0aG9uPC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj5pbXBvcnQg
cHl0ZXN0PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj48YnIgY2xhc3M9ImdtYWlsX21zZyI+
PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj5AcHl0ZXN0LnJlcXVpcmVzX2RlcGVuZGVuY3ko
4oCYPHdicj5zY2lweSZndDs9MC4xNSwgbWF0cGxvdGxpYuKAmSk8L2Rpdj48ZGl2IGNsYXNzPSJn
bWFpbF9tc2ciPmRlZiB0ZXN0X3VzaW5nX3NjaXB5KCk6PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxf
bXNnIj5gYGA8L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPjxiciBjbGFzcz0iZ21haWxfbXNn
Ij48L2Rpdj48ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPlRoYXQncyB0aGUgc2FtZSBtZWNoYW5pc20g
cHl0ZXN0IGl0c2VsZiB1c2VzIHRvIGV4cG9zZSBpdHMgb3duIGJ1aWx0aW4gZnVuY3Rpb25hbGl0
eSBsaWtlIGBweXRlc3QubWFya2AgZm9yIGV4YW1wbGUuPC9kaXY+PC9kaXY+PC9kaXY+PGRpdiBk
aXI9Imx0ciIgY2xhc3M9ImdtYWlsX21zZyI+PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUgZ21haWxf
bXNnIj48ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPjxiciBjbGFzcz0iZ21haWxfbXNnIj48L2Rpdj48
ZGl2IGNsYXNzPSJnbWFpbF9tc2ciPiZuYnNwOzwvZGl2PjxibG9ja3F1b3RlIGNsYXNzPSJnbWFp
bF9xdW90ZSBnbWFpbF9tc2ciIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXItbGVmdDox
cHggI2NjYyBzb2xpZDtwYWRkaW5nLWxlZnQ6MWV4Ij48ZGl2IHN0eWxlPSJ3b3JkLXdyYXA6YnJl
YWstd29yZCIgY2xhc3M9ImdtYWlsX21zZyI+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj48ZGl2IGNs
YXNzPSJnbWFpbF9tc2ciPjxkaXYgY2xhc3M9ImdtYWlsX21zZyI+QXJlIHRoZXJlIG9uZSBvciBh
IGZldyBleGFtcGxlcyBvZiBwbHVnaW5zIHRoYXQgSSBjb3VsZCBsb29rIGF0IGJlZm9yZSBnZXR0
aW5nIHN0YXJ0ZWQgdGhhdCBhcmUgc2ltaWxhciB0byB3aGF0IEnigJltIHRyeWluZyB0byBkbz88
L2Rpdj48L2Rpdj48L2Rpdj48L2Rpdj48L2Jsb2NrcXVvdGU+PGRpdiBjbGFzcz0iZ21haWxfbXNn
Ij48YnIgY2xhc3M9ImdtYWlsX21zZyI+PC9kaXY+PC9kaXY+PC9kaXY+PGRpdiBkaXI9Imx0ciIg
Y2xhc3M9ImdtYWlsX21zZyI+PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUgZ21haWxfbXNnIj48ZGl2
IGNsYXNzPSJnbWFpbF9tc2ciPkNhbid0IHRoaW5rIG9mIG9uZSBvdXQgb2YgdGhlIHRvcCBvZiBt
eSBoZWFkIHJpZ2h0IG5vdywgc29ycnkuJm5ic3A7PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfbXNn
Ij48YnIgY2xhc3M9ImdtYWlsX21zZyI+PC9kaXY+PGRpdiBjbGFzcz0iZ21haWxfbXNnIj5JZiB5
b3UgZ28gYWhlYWQgYW5kIGltcGxlbWVudCBhIHBsdWdpbiwgcGxlYXNlIG1ha2Ugc3VyZSB0byBh
bm5vdW5jZSBoZXJlIGluIHRoZSBsaXN0IGZvciB0aG9zZSBpbnRlcmVzdGVkLiA6KSZuYnNwOzwv
ZGl2PjxkaXYgY2xhc3M9ImdtYWlsX21zZyI+PGJyIGNsYXNzPSJnbWFpbF9tc2ciPjwvZGl2Pjxk
aXYgY2xhc3M9ImdtYWlsX21zZyI+Q2hlZXJzLDwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX21zZyI+
QnJ1bm8uPC9kaXY+PC9kaXY+PC9kaXY+" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></div></div>