You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Change importlib to first try to import modules using the standard mechanism
As detailed in pytest-dev#11475 (comment), currently with `--import-mode=importlib` pytest will try to import every file by using a unique module name, regardless if that module could be imported using the normal import mechanism without touching `sys.path`.
This has the consequence that non-test modules available in `sys.path` (via other mechanism, such as being installed into a virtualenv, PYTHONPATH, etc) would end up being imported as standalone modules, instead of imported with their expected module names.
To illustrate:
```
.env/
lib/
site-packages/
anndata/
core.py
```
Given `anndata` is installed into the virtual environment, `python -c "import anndata.core"` works, but pytest with `importlib` mode would import that module as a standalone module named `".env.lib.site-packages.anndata.core"`, because importlib module was designed to import test files which are not reachable from `sys.path`, but now it is clear that normal modules should be imported using the standard mechanisms if possible.
Now `imporlib` mode will first try to import the module normally, without changing `sys.path`, and if that fails it falls back to importing the module as a standalone module.
This supersedes pytest-dev#11931.
Fixpytest-dev#11475Closepytest-dev#11931
Copy file name to clipboardExpand all lines: doc/en/explanation/pythonpath.rst
+50-11Lines changed: 50 additions & 11 deletions
Original file line number
Diff line number
Diff line change
@@ -16,10 +16,13 @@ import process can be controlled through the ``--import-mode`` command-line flag
16
16
these values:
17
17
18
18
* ``prepend`` (default): the directory path containing each module will be inserted into the *beginning*
19
-
of :py:data:`sys.path` if not already there, and then imported with the :func:`importlib.import_module <importlib.import_module>` function.
19
+
of :py:data:`sys.path` if not already there, and then imported with
20
+
the :func:`importlib.import_module <importlib.import_module>` function.
20
21
21
-
This requires test module names to be unique when the test directory tree is not arranged in
22
-
packages, because the modules will put in :py:data:`sys.modules` after importing.
22
+
It is highly recommended to arrange your test modules as packages by adding ``__init__.py`` files to your directories
23
+
containing tests. If the test directory tree is not arranged as packages, then each test file needs to have a unique name
24
+
compared to the other test files, because the modules will put in :py:data:`sys.modules` after importing
25
+
therefore they need to be globally unique.
23
26
24
27
This is the classic mechanism, dating back from the time Python 2 was still supported.
25
28
@@ -38,26 +41,62 @@ these values:
38
41
the tests will run against the installed version
39
42
of ``pkg_under_test`` when ``--import-mode=append`` is used whereas
40
43
with ``prepend`` they would pick up the local version. This kind of confusion is why
41
-
we advocate for using :ref:`src <src-layout>` layouts.
44
+
we advocate for using :ref:`src-layouts<src-layout>`.
42
45
43
46
Same as ``prepend``, requires test module names to be unique when the test directory tree is
44
47
not arranged in packages, because the modules will put in :py:data:`sys.modules` after importing.
45
48
46
-
* ``importlib``: new in pytest-6.0, this mode uses more fine control mechanisms provided by :mod:`importlib` to import test modules. This gives full control over the import process, and doesn't require changing :py:data:`sys.path`.
49
+
* ``importlib``: this mode uses more fine control mechanisms provided by :mod:`importlib` to import test modules, without changing :py:data:`sys.path`.
47
50
48
-
For this reason this doesn't require test module names to be unique.
51
+
It works like this:
49
52
50
-
One drawback however is that test modules are non-importable by each other. Also, utility
51
-
modules in the tests directories are not automatically importable because the tests directory is no longer
52
-
added to :py:data:`sys.path`.
53
+
1. Given a certain module path, for example ``tests/core/test_models.py``, derives a canonical name
54
+
like ``tests.core.test_models`` and tries to import it.
53
55
54
-
Initially we intended to make ``importlib`` the default in future releases, however it is clear now that
55
-
it has its own set of drawbacks so the default will remain ``prepend`` for the foreseeable future.
56
+
For test modules this will usually fail, as test modules are not usually importable, but will work for modules that are installed into a virtualenv.
57
+
58
+
For non-test modules this also will usually work if they are installed/accessible via ``sys.path``, so
59
+
for example ``.env/lib/site-packages/app/core.py`` will be importable as ``app.core``. This is desirable
60
+
in general, and happens when plugins import non-test modules for other purposes, for example doctesting.
61
+
62
+
If this step succeeds, the module is returned.
63
+
64
+
2. If the previous step fails, we import the module directly using ``importlib`` facilities, which lets us import it without
65
+
changing :py:data:`sys.path`.
66
+
67
+
Because Python requires the module to also be available in ``sys.modules``, pytest derives unique name for it based
68
+
on its relative location from the ``rootdir`` (for example ``tests.core.test_models``)
69
+
and adds the module to ``sys.modules``.
70
+
71
+
Advantages of this mode:
72
+
73
+
* pytest will not change ``sys.path`` at all.
74
+
* Test module names do not need to be unique -- pytest will generate a unique name automatically based on the ``rootdir``.
75
+
76
+
Disadvantages:
77
+
78
+
* Test modules are non-importable by each other.
79
+
* Testing utility modules (for example a ``tests.helpers`` module containing test-related functions/classes)
80
+
in the tests directories are not importable because the tests directory is no longer
81
+
added to :py:data:`sys.path`.
82
+
83
+
Note that by "test utility modules" we mean functions/classes which are imported by
84
+
other tests directly; this does not include fixtures, which should be placed in ``conftest.py`` files and are
85
+
discovered automatically by pytest.
86
+
87
+
.. versionadded:: 6.0
88
+
89
+
.. note::
90
+
91
+
Initially we intended to make ``importlib`` the default in future releases, however it is clear now that
92
+
it has its own set of drawbacks so the default will remain ``prepend`` for the foreseeable future.
0 commit comments