Repository: sopel-irc/sopel

Issue:
Error loading ...: No module named 'pytest' (test_tools.py:159)
I finally saw an updated Sopel version in my pip this early morning PDT, but got a bunch of errors with its missing pytest module:

````
$ pip list --outdated
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
prawcore (0.14.0) - Latest: 0.15.0 [wheel]
sopel (6.5.1) - Latest: 6.5.2 [sdist]
(SopelPython3)ant@MyBox:~$ pip install --upgrade prawcore sopel
Collecting prawcore
  Downloading prawcore-0.15.0-py2.py3-none-any.whl
Collecting sopel
  Downloading sopel-6.5.2.tar.gz (112kB)
    100% |████████████████████████████████| 112kB 2.7MB/s
Requirement already up-to-date: requests<3.0,>=2.6.0 in ./SopelPython3/lib/python3.4/site-packages (from prawcore)
Requirement already up-to-date: xmltodict in ./SopelPython3/lib/python3.4/site-packages (from sopel)
Requirement already up-to-date: pytz in ./SopelPython3/lib/python3.4/site-packages (from sopel)
Requirement already up-to-date: praw<6.0.0,>=4.0.0 in ./SopelPython3/lib/python3.4/site-packages (from sopel)
Requirement already up-to-date: pyenchant in ./SopelPython3/lib/python3.4/site-packages (from sopel)
Requirement already up-to-date: pygeoip in ./SopelPython3/lib/python3.4/site-packages (from sopel)
Requirement already up-to-date: ipython in ./SopelPython3/lib/python3.4/site-packages (from sopel)
Requirement already up-to-date: certifi>=2017.4.17 in ./SopelPython3/lib/python3.4/site-packages (from requests<3.0,>=2.6.0->prawcore)
Requirement already up-to-date: chardet<3.1.0,>=3.0.2 in ./SopelPython3/lib/python3.4/site-packages (from requests<3.0,>=2.6.0->prawcore)
Requirement already up-to-date: idna<2.7,>=2.5 in ./SopelPython3/lib/python3.4/site-packages (from requests<3.0,>=2.6.0->prawcore)
Requirement already up-to-date: urllib3<1.23,>=1.21.1 in ./SopelPython3/lib/python3.4/site-packages (from requests<3.0,>=2.6.0->prawcore)
Requirement already up-to-date: update-checker>=0.16 in ./SopelPython3/lib/python3.4/site-packages (from praw<6.0.0,>=4.0.0->sopel)
Requirement already up-to-date: pickleshare in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: decorator in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: typing; python_version <= "3.4" in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: pygments in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: simplegeneric>0.8 in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: setuptools>=18.5 in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: prompt-toolkit<2.0.0,>=1.0.4 in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: jedi>=0.10 in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: traitlets>=4.2 in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: pexpect; sys_platform != "win32" in ./SopelPython3/lib/python3.4/site-packages (from ipython->sopel)
Requirement already up-to-date: six>=1.9.0 in ./SopelPython3/lib/python3.4/site-packages (from prompt-toolkit<2.0.0,>=1.0.4->ipython->sopel)
Requirement already up-to-date: wcwidth in ./SopelPython3/lib/python3.4/site-packages (from prompt-toolkit<2.0.0,>=1.0.4->ipython->sopel)
Requirement already up-to-date: parso==0.1.1 in ./SopelPython3/lib/python3.4/site-packages (from jedi>=0.10->ipython->sopel)
Requirement already up-to-date: ipython-genutils in ./SopelPython3/lib/python3.4/site-packages (from traitlets>=4.2->ipython->sopel)
Requirement already up-to-date: ptyprocess>=0.5 in ./SopelPython3/lib/python3.4/site-packages (from pexpect; sys_platform != "win32"->ipython->sopel)
Building wheels for collected packages: sopel
  Running setup.py bdist_wheel for sopel ... done
  Stored in directory: /home/ant/.cache/pip/wheels/6d/f1/de/28d0545ffbb85c84e6b9ce2087e8fa67796cf6e522584f70b6
Successfully built sopel
Installing collected packages: prawcore, sopel
  Found existing installation: prawcore 0.14.0
    Uninstalling prawcore-0.14.0:
      Successfully uninstalled prawcore-0.14.0
  Found existing installation: sopel 6.5.1
    Uninstalling sopel-6.5.1:
      Successfully uninstalled sopel-6.5.1
Successfully installed prawcore-0.15.0 sopel-6.5.2
````

I exited my Sopel bot in IRC like: `/msg mysopelbot .quit command`

````
(SopelPython3)ant@MyBox:~$ sopel -d
Welcome to Sopel. Loading modules...
Downloading malwaredomains db...
Error loading units: No module named 'pytest' (test_tools.py:159)
Error loading xkcd: No module named 'pytest' (test_tools.py:159)
Error loading search: No module named 'pytest' (test_tools.py:159)
Error loading rand: No module named 'pytest' (test_tools.py:159)
Error loading habitica: invalid syntax (common.py, line 25) (../sopel_modules/habitica/__init__.py:7)
Error loading wolfram: No module named 'pytest' (test_tools.py:159)
Error loading calc: No module named 'pytest' (test_tools.py:159)
Error loading meetbot: No module named 'pytest' (test_tools.py:159)
Error loading dice: No module named 'pytest' (test_tools.py:159)
Error loading url: No module named 'pytest' (test_tools.py:159)
Error loading ip: No module named 'pytest' (test_tools.py:159)
Error loading unicode_info: No module named 'pytest' (test_tools.py:159)
Error loading movie: No module named 'pytest' (test_tools.py:159)
Error loading translate: No module named 'pytest' (test_tools.py:159)


Registered 34 modules,
14 modules failed to load


Connecting to irc.someserver.com:6697...
Connected.


$ python -v
...
Python 3.4.2 (default, Oct  8 2014, 10:45:20)
[GCC 4.9.1] on linux
````

A lot of commands don't work like http://google.com, .xkcd, etc. I assume this is related. What's up? :( Thank you in advance. :)


Discussion:
@nfearnley Related to #1287? Looks like we need a way to insert test stuff into callables only if running under `pytest` (or at least bail out if `pytest` isn't installed, instead of failing the whole module load).

@antdude `pip install pytest` as a workaround, and restart your bot again. We'll get this sorted out.
Yes, I see the problem. We can wrap it in a try catch, similar to the python 3 wrappers.
If we add a test here: https://github.com/sopel-irc/sopel/blob/0fdddfb5f831844a58aff9c0a08ebddbefe459c1/sopel/module.py#L444
to check for pytest, it should prevent this issue. There's no need to monkeypatch on the test functions anyways, if we don't have pytest.
Right. Can you make this next on your Sopel to-do list? It's a big enough issue to warrant its own patch release once fixed.
Will do.

On Sun, Apr 1, 2018, 10:06 PM dgw, <notifications@github.com> wrote:

> Right. Can you make this next on your Sopel to-do list? It's a big enough
> issue to warrant its own patch release once fixed.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/sopel-irc/sopel/issues/1294#issuecomment-377836864>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAiTgredV1_Y671-0cWRMAF7CRc9tTbzks5tkYeigaJpZM4TC1x1>
> .
>

Thanks. Pip installing pytest package fixed it for me.
I've added a patch that should hopefully fix this: https://github.com/sopel-irc/sopel/pull/1295

Resolving patch:
diff --git a/sopel/module.py b/sopel/module.py
--- a/sopel/module.py
+++ b/sopel/module.py
@@ -441,7 +441,11 @@ def __call__(self, func):
         if not hasattr(func, "example"):
             func.example = []
 
-        if self.result:
+        import sys
+
+        # only inject test-related stuff if we're running tests
+        # see https://stackoverflow.com/a/44595269/5991
+        if 'pytest' in sys.modules and self.result:
             test = sopel.test_tools.get_example_test(
                 func, self.msg, self.result, self.privmsg, self.admin,
                 self.owner, self.repeat, self.use_re, self.ignore


Test patch: