diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0d48982d6..95d7df04c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -85,7 +85,7 @@ jobs: - name: Install tox run: | - python -m pip install --upgrade pip + python -Im pip install --upgrade pip pip install --upgrade tox - name: Generate release notes diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index 1bb23fab8..e938218f2 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -38,7 +38,7 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip + python -Im pip install --upgrade pip pip install --upgrade setuptools tox - name: Prepare release PR (minor/patch release) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 363cbe901..173bc5434 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -186,7 +186,7 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip + python -Im pip install --upgrade pip pip install tox coverage - name: Test without coverage @@ -201,7 +201,7 @@ jobs: - name: Generate coverage report if: "matrix.use_coverage" - run: python -m coverage xml + run: python -Im coverage xml - name: Upload coverage to Codecov if: "matrix.use_coverage" diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 214d734c9..d524ca557 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -38,7 +38,7 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip + python -Im pip install --upgrade pip pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 6f55c230c..34ea7ce6b 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -299,7 +299,7 @@ Here is a simple overview, with pytest-specific bits: #. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and use an editable install with the ``testing`` extra:: - $ python3 -m venv .venv + $ python3 -Im venv .venv $ source .venv/bin/activate # Linux $ .venv/Scripts/activate.bat # Windows $ pip install -e ".[testing]" diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index efde420cd..030653b05 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -137,7 +137,7 @@ which are better explained in this excellent `blog post`_ by Ionel Cristian Măr directory) you can rely on the fact that Python by default puts the current directory in ``sys.path`` to import your package and run ``python -m pytest`` to execute the tests against the local copy directly. - See :ref:`pytest vs python -m pytest` for more information about the difference between calling ``pytest`` and + See :ref:`pytest vs python -Im pytest` for more information about the difference between calling ``pytest`` and ``python -m pytest``. Tests as part of application code diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst index 5b533f47f..0d3c51615 100644 --- a/doc/en/explanation/pythonpath.rst +++ b/doc/en/explanation/pythonpath.rst @@ -130,13 +130,13 @@ imported in the global import namespace. This is also discussed in details in :ref:`test discovery`. -.. _`pytest vs python -m pytest`: +.. _`pytest vs python -Im pytest`: -Invoking ``pytest`` versus ``python -m pytest`` ------------------------------------------------ +Invoking ``pytest`` versus ``python -Im pytest`` +------------------------------------------------ -Running pytest with ``pytest [...]`` instead of ``python -m pytest [...]`` yields nearly -equivalent behaviour, except that the latter will add the current directory to ``sys.path``, which -is standard ``python`` behavior. +Running pytest with ``pytest [...]`` instead of ``python -Im pytest [...]`` yields nearly +equivalent behaviour, except that the latter will add the current directory to ``sys.path`` +in case when ``-I`` is omitted, which is standard ``python`` behavior. See also :ref:`invoke-python`. diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 65f9debd8..0929e336d 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -158,17 +158,20 @@ Other ways of calling pytest .. _invoke-python: -Calling pytest through ``python -m pytest`` +Calling pytest through ``python -Im pytest`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can invoke testing through the Python interpreter from the command line: .. code-block:: text - python -m pytest [...] + python -Im pytest [...] -This is almost equivalent to invoking the command line script ``pytest [...]`` -directly, except that calling via ``python`` will also add the current directory to ``sys.path``. +This is equivalent to invoking the command line script ``pytest [...]`` +directly, for as long as ``-I`` is used. Dropping it will also add the current +directory to ``sys.path``, which may have a side effect of not `testing your +project as installed +`__. .. _`pytest.main-usage`: diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index ae8709e5e..3e5197706 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -98,7 +98,7 @@ def pytest_addoption(parser: Parser) -> None: choices=("inprocess", "subprocess"), help=( "Run pytest sub runs in tests using an 'inprocess' " - "or 'subprocess' (python -m main) method" + "or 'subprocess' (python -Im main) method" ), ) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 64e65f313..5c5f3a2c0 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -592,17 +592,17 @@ class TestInvocationVariants: def test_python_minus_m_invocation_ok(self, pytester: Pytester) -> None: p1 = pytester.makepyfile("def test_hello(): pass") - res = pytester.run(sys.executable, "-m", "pytest", str(p1)) + res = pytester.run(sys.executable, "-Im", "pytest", str(p1)) assert res.ret == 0 def test_python_minus_m_invocation_fail(self, pytester: Pytester) -> None: p1 = pytester.makepyfile("def test_fail(): 0/0") - res = pytester.run(sys.executable, "-m", "pytest", str(p1)) + res = pytester.run(sys.executable, "-Im", "pytest", str(p1)) assert res.ret == 1 def test_python_pytest_package(self, pytester: Pytester) -> None: p1 = pytester.makepyfile("def test_pass(): pass") - res = pytester.run(sys.executable, "-m", "pytest", str(p1)) + res = pytester.run(sys.executable, "-Im", "pytest", str(p1)) assert res.ret == 0 res.stdout.fnmatch_lines(["*1 passed*"]) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 640890e9a..0155b50bf 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1703,18 +1703,18 @@ def test_exception_handling_no_traceback(pytester: Pytester) -> None: "cmdline_args, warning_output", [ ( - ["-OO", "-m", "pytest", "-h"], + ["-OO", "-Im", "pytest", "-h"], ["warning :*PytestConfigWarning:*assert statements are not executed*"], ), ( - ["-OO", "-m", "pytest"], + ["-OO", "-Im", "pytest"], [ "=*= warnings summary =*=", "*PytestConfigWarning:*assert statements are not executed*", ], ), ( - ["-OO", "-m", "pytest", "--assert=plain"], + ["-OO", "-Im", "pytest", "--assert=plain"], [ "=*= warnings summary =*=", "*PytestConfigWarning: ASSERTIONS ARE NOT EXECUTED and FAILING TESTS WILL PASS. " diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index b2d547931..b38dd87e3 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -315,7 +315,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: # http://stackoverflow.com/q/12589419/1307905 # so we use bash fp.write( - 'COMP_WORDBREAKS="$COMP_WORDBREAKS" {} -m pytest 8>&1 9>&2'.format( + 'COMP_WORDBREAKS="$COMP_WORDBREAKS" {} -Im pytest 8>&1 9>&2'.format( shlex.quote(sys.executable) ) ) diff --git a/testing/test_setuponly.py b/testing/test_setuponly.py index 0f70383a6..4a9d86d57 100644 --- a/testing/test_setuponly.py +++ b/testing/test_setuponly.py @@ -314,6 +314,6 @@ def test_show_fixture_action_with_bytes(pytester: Pytester) -> None: """ ) result = pytester.run( - sys.executable, "-bb", "-m", "pytest", "--setup-show", str(test_file) + sys.executable, "-bb", "-Im", "pytest", "--setup-show", str(test_file) ) assert result.ret == 0 diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 2f0ab9b54..294b892e3 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -792,7 +792,7 @@ def test_warning_on_testpaths_not_found(pytester: Pytester) -> None: ) -def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) -> None: +def test_resource_warning(pytester: Pytester) -> None: # Some platforms (notably PyPy) don't have tracemalloc. # We choose to explicitly not skip this in case tracemalloc is not # available, using `importorskip("tracemalloc")` for example, @@ -804,10 +804,6 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) - except ImportError: has_tracemalloc = False - # Explicitly disable PYTHONTRACEMALLOC in case pytest's test suite is running - # with it enabled. - monkeypatch.delenv("PYTHONTRACEMALLOC", raising=False) - pytester.makepyfile( """ def open_file(p): @@ -820,7 +816,9 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) - open_file(p) """ ) - result = pytester.run(sys.executable, "-Xdev", "-m", "pytest") + # Explicitly disable PYTHONTRACEMALLOC in case pytest's test suite is running + # with it enabled. + result = pytester.run(sys.executable, "-Xdev", "-Xtracemalloc=0", "-Im", "pytest") expected_extra = ( [ "*ResourceWarning* unclosed file*", @@ -832,9 +830,7 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) - ) result.stdout.fnmatch_lines([*expected_extra, "*1 passed*"]) - monkeypatch.setenv("PYTHONTRACEMALLOC", "20") - - result = pytester.run(sys.executable, "-Xdev", "-m", "pytest") + result = pytester.run(sys.executable, "-Xdev", "-Xtracemalloc=20", "-Im", "pytest") expected_extra = ( [ "*ResourceWarning* unclosed file*", diff --git a/tox.ini b/tox.ini index b5c28029f..9c4d24ef2 100644 --- a/tox.ini +++ b/tox.ini @@ -129,7 +129,7 @@ setenv = pip_pre=true # use latest pip to get new dependency resolver (#7783) download=true -install_command=python -m pip install {opts} {packages} +install_command=python -Im pip install {opts} {packages} changedir = testing/plugins_integration deps = -rtesting/plugins_integration/requirements.txt setenv =