JamesHutchison / pytest-hot-reloading

A hot reloading pytest daemon, implemented as a plugin
MIT License
95 stars 2 forks source link

`pytest <single-test>` fails with `pytest.PytestAssertRewriteWarning: Module already imported so cannot be rewritten: anyio` #88

Open tamird opened 5 months ago

tamird commented 5 months ago

Very cool project. Sadly it seems not to work with my project and doesn't emit much information.

tamird@MacBook-Pro common % poetry run pytest <my-test-case>
Daemon took 0.023 seconds to reply

Traceback (most recent call last):
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/pytest_hot_reloading/daemon.py", line 193, in run_pytest
    status_code = pytest.main(["--color=yes"] + args)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 159, in main
    config = _prepareconfig(args, plugins)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 346, in _prepareconfig
    config = pluginmanager.hook.pytest_cmdline_parse(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/pluggy/_hooks.py", line 513, in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/pluggy/_manager.py", line 120, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/pluggy/_callers.py", line 139, in _multicall
    raise exception.with_traceback(exception.__traceback__)
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/pluggy/_callers.py", line 122, in _multicall
    teardown.throw(exception)  # type: ignore[union-attr]
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/helpconfig.py", line 106, in pytest_cmdline_parse
    config = yield
             ^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/pluggy/_callers.py", line 103, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 1152, in pytest_cmdline_parse
    self.parse(args)
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 1501, in parse
    self._preparse(args, addopts=addopts)
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 1383, in _preparse
    self._consider_importhook(args)
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 1285, in _consider_importhook
    self._mark_plugins_for_rewrite(hook)
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 1306, in _mark_plugins_for_rewrite
    hook.mark_rewrite(name)
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/assertion/rewrite.py", line 267, in mark_rewrite
    self._warn_already_imported(name)
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/assertion/rewrite.py", line 274, in _warn_already_imported
    self.config.issue_config_time_warning(
  File "/Users/tamird/Library/Caches/pypoetry/virtualenvs/common-hf-Ms37h-py3.11/lib/python3.11/site-packages/_pytest/config/__init__.py", line 1539, in issue_config_time_warning
    warnings.warn(warning, stacklevel=stacklevel)
pytest.PytestAssertRewriteWarning: Module already imported so cannot be rewritten: anyio
JamesHutchison commented 5 months ago

Hey thanks for bringing this to my attention! I'm wondering if you have a plugin or something in your config that's not compatible? I'm not familiar with that library. Supposedly importing pytest first should fix this, but I would think that's how its being ran?

Does it work if you do poetry run python -m pytest <my-test-case>?

tamird commented 5 months ago

The behavior is sadly the same with python -m pytest. How can I go debugging?

JamesHutchison commented 5 months ago

I see a couple things:

addopts = "-n 1 -p pytest_hot_reloading.plugin -p megamock.plugins.pytest"

You can also try disabling the anyio plugin. I'm guessing it's -p no:anyio but I'm not sure

tamird commented 5 months ago

I see a couple things:

  • This is a warning so it shouldn't cause anything to fail unless you've enabled warnings as errors. You can squelch this warning to make it go away (ask ChatGPT how). If you're not testing anyio specifically, I don't see the harm in this warning.

You're right, we have all warnings turned up to errors. Suppressing this one unblocks me.

  • I haven't used anyio, so the question I would have is whether it's even necessary

We aren't using it directly. anyio isn't a plugin, it's a "plain old library": https://github.com/agronholm/anyio. We aren't using it directly, it's a transitive dependency that doesn't appear by name in our code. It's a dependency of httpx.

  • Are you able to confirm that this plugin is indeed causing the issue? Does changing the plugin order (the order they are defined can matter) resolve the issue? We have the hot reloading plugin FIRST

addopts = "-n 1 -p pytest_hot_reloading.plugin -p megamock.plugins.pytest"

You can also try disabling the anyio plugin. I'm guessing it's -p no:anyio but I'm not sure

I'm not sure how to use this advice (particularly the bit about loading order) given anyio isn't a plugin.

tamird commented 5 months ago

By the way, after suppressing the warning I get a new failure mode when I run the tests for the second time. EDIT: gist

JamesHutchison commented 5 months ago

Based on the docs it appears to have a plugin that I'm guessing is executed automatically

https://anyio.readthedocs.io/en/stable/testing.html

JamesHutchison commented 5 months ago

Have you tried setting pytest to the version that matches what this library is using? 7.2.2

tamird commented 5 months ago

I haven't - I'm on pytest 8.2.2. What would it take to make this compatible with pytest 8?