Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conftest.restore_import_state should restore sys.meta_path as well as sys.path #1140

Merged
merged 6 commits into from Apr 23, 2023

Conversation

dairiki
Copy link
Contributor

@dairiki dairiki commented Apr 23, 2023

The restore_import_state context manager (in conftest.py) is used to isolate tests with respect to any changes they may make in sys.path and any modules they may import.

It turns out that sys.meta_path needs to be restored as well. If that's not done, there are a couple of insidious bugs (spurious test failures) that crop up.

Issue(s) Resolved

Spurious test failures.

Description of Changes

  • Wrote at least one-line docstrings (for any new functions)
  • Added unit test(s) covering the changes (if testable)

Restore sys.meta_path.

Some modules, when imported, add their own custom finders to sys.meta_path. If such a module is imported within a test that is protected by restore_import_state, it is in effect, "unimported" at the end of the test. If another test also imports that module, it can add its finder to meta_path again.

(This can result in a RuntimeError: Plugin "webpack-support" is already registered, since, with a duplicate finder on meta_path, import.metadata.distributions() can list all distributions twice.)

Demangle the finders on sys.meta_path

It gets worse.

It turns out that when importlib_metadata is imported, it neuters the stdlib PathFinder (by deleting its find_distributions method). It then adds its own custom finder to handle distribution lookup instead.

If importlib_metadata is imported within a test that is protected by restore_import_state, its custom finder gets removed from sys.meta_path at the end of the test. But the stdlib finder has been crippled at this point, so now attempts to list installed distributions fail.

So here, we make a copy of the stdlib PathFinder before the test run and restore that at the end of the test.

Now that restore_import_state restores meta_path, don't use
monkeypatch to do that as well.

That the ordering between the monkeypatch's and restore_import_state's
teardown execution is indeterminate, so using both can cause problems.
Clean up the code a bit.

Also, out of paranoia, also restore sys.path_hooks.
@dairiki dairiki marked this pull request as ready for review April 23, 2023 17:59
@dairiki dairiki merged commit b834585 into lektor:master Apr 23, 2023
15 checks passed
@dairiki dairiki deleted the fix.restore_import_state branch April 24, 2023 18:05
dairiki added a commit to dairiki/lektor that referenced this pull request Sep 11, 2023
… sys.path (lektor#1140)

* test(conftest.restore_import_state): ensure sys.meta_path is restored

* fix(conftest.restore_import_state): restore sys.meta_path

* fix(test_pluginsystem): preserve sys.meta_path

* refactor(conftest.restore_import_state): cleanup & paranoia

* test(tests): check that tests do not alter sys.path

* fix(tests): fix the tests that were munging sys.path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant