From f981682bdc0ca0235d04629c358643be610a860d Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Thu, 18 Nov 2021 15:08:59 +0100 Subject: [PATCH] Allow recent pytest versions to be used with Spack (#25371) Currently Spack vendors `pytest` at a version which is three major versions behind the latest (3.2.5 vs. 6.2.4). We do that since v3.2.5 is the latest version supporting Python 2.6. Remaining so much behind the currently supported versions though might introduce some incompatibilities and is surely a technical debt. This PR modifies Spack to: - Use the vendored `pytest@3.2.5` only as a fallback solution, if the Python interpreter used for Spack doesn't provide a newer one - Be able to parse `pytest --collect-only` in all the different output formats from v3.2.5 to v6.2.4 and use it consistently for `spack unit-test --list-*` - Updating the unit tests in Github Actions to use a more recent `pytest` version --- .github/workflows/unit_tests.yaml | 8 +- lib/spack/docs/conf.py | 1 + .../{ => pytest-fallback}/_pytest/LICENSE | 0 .../{ => pytest-fallback}/_pytest/__init__.py | 0 .../_pytest/_argcomplete.py | 0 .../_pytest/_code/__init__.py | 0 .../_pytest/_code/_py2traceback.py | 0 .../_pytest/_code/code.py | 0 .../_pytest/_code/source.py | 0 .../{ => pytest-fallback}/_pytest/_pluggy.py | 0 .../{ => pytest-fallback}/_pytest/_version.py | 0 .../_pytest/assertion/__init__.py | 0 .../_pytest/assertion/rewrite.py | 0 .../_pytest/assertion/truncate.py | 0 .../_pytest/assertion/util.py | 0 .../_pytest/cacheprovider.py | 0 .../{ => pytest-fallback}/_pytest/capture.py | 0 .../{ => pytest-fallback}/_pytest/compat.py | 0 .../{ => pytest-fallback}/_pytest/config.py | 0 .../_pytest/debugging.py | 0 .../_pytest/deprecated.py | 0 .../{ => pytest-fallback}/_pytest/doctest.py | 0 .../{ => pytest-fallback}/_pytest/fixtures.py | 0 .../_pytest/freeze_support.py | 0 .../_pytest/helpconfig.py | 0 .../{ => pytest-fallback}/_pytest/hookspec.py | 0 .../{ => pytest-fallback}/_pytest/junitxml.py | 0 .../{ => pytest-fallback}/_pytest/main.py | 0 .../{ => pytest-fallback}/_pytest/mark.py | 0 .../_pytest/monkeypatch.py | 0 .../{ => pytest-fallback}/_pytest/nodes.py | 0 .../{ => pytest-fallback}/_pytest/nose.py | 0 .../{ => pytest-fallback}/_pytest/outcomes.py | 0 .../{ => pytest-fallback}/_pytest/pastebin.py | 0 .../{ => pytest-fallback}/_pytest/pytester.py | 0 .../{ => pytest-fallback}/_pytest/python.py | 0 .../_pytest/python_api.py | 0 .../{ => pytest-fallback}/_pytest/recwarn.py | 0 .../_pytest/resultlog.py | 0 .../{ => pytest-fallback}/_pytest/runner.py | 0 .../_pytest/setuponly.py | 0 .../_pytest/setupplan.py | 0 .../{ => pytest-fallback}/_pytest/skipping.py | 0 .../{ => pytest-fallback}/_pytest/terminal.py | 0 .../{ => pytest-fallback}/_pytest/tmpdir.py | 0 .../{ => pytest-fallback}/_pytest/unittest.py | 0 .../_pytest/vendored_packages/README.md | 0 .../_pytest/vendored_packages/__init__.py | 0 .../pluggy-0.4.0.dist-info/DESCRIPTION.rst | 0 .../pluggy-0.4.0.dist-info/INSTALLER | 0 .../pluggy-0.4.0.dist-info/LICENSE.txt | 0 .../pluggy-0.4.0.dist-info/METADATA | 0 .../pluggy-0.4.0.dist-info/RECORD | 0 .../pluggy-0.4.0.dist-info/WHEEL | 0 .../pluggy-0.4.0.dist-info/metadata.json | 0 .../pluggy-0.4.0.dist-info/top_level.txt | 0 .../_pytest/vendored_packages/pluggy.py | 0 .../{ => pytest-fallback}/_pytest/warnings.py | 0 .../{ => pytest-fallback}/py/__init__.py | 0 .../{ => pytest-fallback}/py/__metainfo.py | 0 .../{ => pytest-fallback}/py/_apipkg.py | 0 .../{ => pytest-fallback}/py/_builtin.py | 0 .../py/_code/__init__.py | 0 .../py/_code/_assertionnew.py | 0 .../py/_code/_assertionold.py | 0 .../py/_code/_py2traceback.py | 0 .../py/_code/assertion.py | 0 .../{ => pytest-fallback}/py/_code/code.py | 0 .../{ => pytest-fallback}/py/_code/source.py | 0 .../{ => pytest-fallback}/py/_error.py | 0 .../{ => pytest-fallback}/py/_iniconfig.py | 0 .../{ => pytest-fallback}/py/_io/__init__.py | 0 .../{ => pytest-fallback}/py/_io/capture.py | 0 .../{ => pytest-fallback}/py/_io/saferepr.py | 0 .../py/_io/terminalwriter.py | 0 .../{ => pytest-fallback}/py/_log/__init__.py | 0 .../{ => pytest-fallback}/py/_log/log.py | 0 .../{ => pytest-fallback}/py/_log/warning.py | 0 .../py/_path/__init__.py | 0 .../py/_path/cacheutil.py | 0 .../{ => pytest-fallback}/py/_path/common.py | 0 .../{ => pytest-fallback}/py/_path/local.py | 0 .../{ => pytest-fallback}/py/_path/svnurl.py | 0 .../{ => pytest-fallback}/py/_path/svnwc.py | 0 .../py/_process/__init__.py | 0 .../py/_process/cmdexec.py | 0 .../py/_process/forkedfunc.py | 0 .../py/_process/killproc.py | 0 .../external/{ => pytest-fallback}/py/_std.py | 0 .../{ => pytest-fallback}/py/_xmlgen.py | 0 .../external/{ => pytest-fallback}/py/test.py | 0 .../external/{ => pytest-fallback}/pytest.py | 0 lib/spack/spack/cmd/unit_test.py | 110 ++++++++++++------ lib/spack/spack/test/cmd/unit_test.py | 5 +- lib/spack/spack/test/conftest.py | 12 +- 95 files changed, 92 insertions(+), 44 deletions(-) rename lib/spack/external/{ => pytest-fallback}/_pytest/LICENSE (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/_argcomplete.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/_code/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/_code/_py2traceback.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/_code/code.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/_code/source.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/_pluggy.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/_version.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/assertion/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/assertion/rewrite.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/assertion/truncate.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/assertion/util.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/cacheprovider.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/capture.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/compat.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/config.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/debugging.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/deprecated.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/doctest.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/fixtures.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/freeze_support.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/helpconfig.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/hookspec.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/junitxml.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/main.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/mark.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/monkeypatch.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/nodes.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/nose.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/outcomes.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/pastebin.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/pytester.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/python.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/python_api.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/recwarn.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/resultlog.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/runner.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/setuponly.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/setupplan.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/skipping.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/terminal.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/tmpdir.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/unittest.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/README.md (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/DESCRIPTION.rst (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/INSTALLER (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/LICENSE.txt (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/METADATA (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/RECORD (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/WHEEL (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/metadata.json (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy-0.4.0.dist-info/top_level.txt (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/vendored_packages/pluggy.py (100%) rename lib/spack/external/{ => pytest-fallback}/_pytest/warnings.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/__metainfo.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_apipkg.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_builtin.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_code/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_code/_assertionnew.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_code/_assertionold.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_code/_py2traceback.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_code/assertion.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_code/code.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_code/source.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_error.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_iniconfig.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_io/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_io/capture.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_io/saferepr.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_io/terminalwriter.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_log/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_log/log.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_log/warning.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_path/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_path/cacheutil.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_path/common.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_path/local.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_path/svnurl.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_path/svnwc.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_process/__init__.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_process/cmdexec.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_process/forkedfunc.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_process/killproc.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_std.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/_xmlgen.py (100%) rename lib/spack/external/{ => pytest-fallback}/py/test.py (100%) rename lib/spack/external/{ => pytest-fallback}/pytest.py (100%) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 764a9cdcf04..2e8f9deef69 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -114,7 +114,7 @@ jobs: patchelf cmake bison libbison-dev kcov - name: Install Python packages run: | - pip install --upgrade pip six setuptools codecov coverage[toml] + pip install --upgrade pip six setuptools pytest codecov coverage[toml] # ensure style checks are not skipped in unit tests for python >= 3.6 # note that true/false (i.e., 1/0) are opposite in conditions in python and bash if python -c 'import sys; sys.exit(not sys.version_info >= (3, 6))'; then @@ -173,7 +173,7 @@ jobs: sudo apt-get install -y coreutils kcov csh zsh tcsh fish dash bash - name: Install Python packages run: | - pip install --upgrade pip six setuptools codecov coverage[toml] + pip install --upgrade pip six setuptools pytest codecov coverage[toml] - name: Setup git configuration run: | # Need this for the git tests to succeed. @@ -274,7 +274,7 @@ jobs: patchelf kcov - name: Install Python packages run: | - pip install --upgrade pip six setuptools codecov coverage[toml] clingo + pip install --upgrade pip six setuptools pytest codecov coverage[toml] clingo - name: Setup git configuration run: | # Need this for the git tests to succeed. @@ -317,7 +317,7 @@ jobs: - name: Install Python packages run: | pip install --upgrade pip six setuptools - pip install --upgrade codecov coverage[toml] + pip install --upgrade pytest codecov coverage[toml] - name: Setup Homebrew packages run: | brew install dash fish gcc gnupg2 kcov diff --git a/lib/spack/docs/conf.py b/lib/spack/docs/conf.py index 2b58223e1dc..d0a2bb9e339 100644 --- a/lib/spack/docs/conf.py +++ b/lib/spack/docs/conf.py @@ -30,6 +30,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('_spack_root/lib/spack/external')) +sys.path.insert(0, os.path.abspath('_spack_root/lib/spack/external/pytest-fallback')) if sys.version_info[0] < 3: sys.path.insert( diff --git a/lib/spack/external/_pytest/LICENSE b/lib/spack/external/pytest-fallback/_pytest/LICENSE similarity index 100% rename from lib/spack/external/_pytest/LICENSE rename to lib/spack/external/pytest-fallback/_pytest/LICENSE diff --git a/lib/spack/external/_pytest/__init__.py b/lib/spack/external/pytest-fallback/_pytest/__init__.py similarity index 100% rename from lib/spack/external/_pytest/__init__.py rename to lib/spack/external/pytest-fallback/_pytest/__init__.py diff --git a/lib/spack/external/_pytest/_argcomplete.py b/lib/spack/external/pytest-fallback/_pytest/_argcomplete.py similarity index 100% rename from lib/spack/external/_pytest/_argcomplete.py rename to lib/spack/external/pytest-fallback/_pytest/_argcomplete.py diff --git a/lib/spack/external/_pytest/_code/__init__.py b/lib/spack/external/pytest-fallback/_pytest/_code/__init__.py similarity index 100% rename from lib/spack/external/_pytest/_code/__init__.py rename to lib/spack/external/pytest-fallback/_pytest/_code/__init__.py diff --git a/lib/spack/external/_pytest/_code/_py2traceback.py b/lib/spack/external/pytest-fallback/_pytest/_code/_py2traceback.py similarity index 100% rename from lib/spack/external/_pytest/_code/_py2traceback.py rename to lib/spack/external/pytest-fallback/_pytest/_code/_py2traceback.py diff --git a/lib/spack/external/_pytest/_code/code.py b/lib/spack/external/pytest-fallback/_pytest/_code/code.py similarity index 100% rename from lib/spack/external/_pytest/_code/code.py rename to lib/spack/external/pytest-fallback/_pytest/_code/code.py diff --git a/lib/spack/external/_pytest/_code/source.py b/lib/spack/external/pytest-fallback/_pytest/_code/source.py similarity index 100% rename from lib/spack/external/_pytest/_code/source.py rename to lib/spack/external/pytest-fallback/_pytest/_code/source.py diff --git a/lib/spack/external/_pytest/_pluggy.py b/lib/spack/external/pytest-fallback/_pytest/_pluggy.py similarity index 100% rename from lib/spack/external/_pytest/_pluggy.py rename to lib/spack/external/pytest-fallback/_pytest/_pluggy.py diff --git a/lib/spack/external/_pytest/_version.py b/lib/spack/external/pytest-fallback/_pytest/_version.py similarity index 100% rename from lib/spack/external/_pytest/_version.py rename to lib/spack/external/pytest-fallback/_pytest/_version.py diff --git a/lib/spack/external/_pytest/assertion/__init__.py b/lib/spack/external/pytest-fallback/_pytest/assertion/__init__.py similarity index 100% rename from lib/spack/external/_pytest/assertion/__init__.py rename to lib/spack/external/pytest-fallback/_pytest/assertion/__init__.py diff --git a/lib/spack/external/_pytest/assertion/rewrite.py b/lib/spack/external/pytest-fallback/_pytest/assertion/rewrite.py similarity index 100% rename from lib/spack/external/_pytest/assertion/rewrite.py rename to lib/spack/external/pytest-fallback/_pytest/assertion/rewrite.py diff --git a/lib/spack/external/_pytest/assertion/truncate.py b/lib/spack/external/pytest-fallback/_pytest/assertion/truncate.py similarity index 100% rename from lib/spack/external/_pytest/assertion/truncate.py rename to lib/spack/external/pytest-fallback/_pytest/assertion/truncate.py diff --git a/lib/spack/external/_pytest/assertion/util.py b/lib/spack/external/pytest-fallback/_pytest/assertion/util.py similarity index 100% rename from lib/spack/external/_pytest/assertion/util.py rename to lib/spack/external/pytest-fallback/_pytest/assertion/util.py diff --git a/lib/spack/external/_pytest/cacheprovider.py b/lib/spack/external/pytest-fallback/_pytest/cacheprovider.py similarity index 100% rename from lib/spack/external/_pytest/cacheprovider.py rename to lib/spack/external/pytest-fallback/_pytest/cacheprovider.py diff --git a/lib/spack/external/_pytest/capture.py b/lib/spack/external/pytest-fallback/_pytest/capture.py similarity index 100% rename from lib/spack/external/_pytest/capture.py rename to lib/spack/external/pytest-fallback/_pytest/capture.py diff --git a/lib/spack/external/_pytest/compat.py b/lib/spack/external/pytest-fallback/_pytest/compat.py similarity index 100% rename from lib/spack/external/_pytest/compat.py rename to lib/spack/external/pytest-fallback/_pytest/compat.py diff --git a/lib/spack/external/_pytest/config.py b/lib/spack/external/pytest-fallback/_pytest/config.py similarity index 100% rename from lib/spack/external/_pytest/config.py rename to lib/spack/external/pytest-fallback/_pytest/config.py diff --git a/lib/spack/external/_pytest/debugging.py b/lib/spack/external/pytest-fallback/_pytest/debugging.py similarity index 100% rename from lib/spack/external/_pytest/debugging.py rename to lib/spack/external/pytest-fallback/_pytest/debugging.py diff --git a/lib/spack/external/_pytest/deprecated.py b/lib/spack/external/pytest-fallback/_pytest/deprecated.py similarity index 100% rename from lib/spack/external/_pytest/deprecated.py rename to lib/spack/external/pytest-fallback/_pytest/deprecated.py diff --git a/lib/spack/external/_pytest/doctest.py b/lib/spack/external/pytest-fallback/_pytest/doctest.py similarity index 100% rename from lib/spack/external/_pytest/doctest.py rename to lib/spack/external/pytest-fallback/_pytest/doctest.py diff --git a/lib/spack/external/_pytest/fixtures.py b/lib/spack/external/pytest-fallback/_pytest/fixtures.py similarity index 100% rename from lib/spack/external/_pytest/fixtures.py rename to lib/spack/external/pytest-fallback/_pytest/fixtures.py diff --git a/lib/spack/external/_pytest/freeze_support.py b/lib/spack/external/pytest-fallback/_pytest/freeze_support.py similarity index 100% rename from lib/spack/external/_pytest/freeze_support.py rename to lib/spack/external/pytest-fallback/_pytest/freeze_support.py diff --git a/lib/spack/external/_pytest/helpconfig.py b/lib/spack/external/pytest-fallback/_pytest/helpconfig.py similarity index 100% rename from lib/spack/external/_pytest/helpconfig.py rename to lib/spack/external/pytest-fallback/_pytest/helpconfig.py diff --git a/lib/spack/external/_pytest/hookspec.py b/lib/spack/external/pytest-fallback/_pytest/hookspec.py similarity index 100% rename from lib/spack/external/_pytest/hookspec.py rename to lib/spack/external/pytest-fallback/_pytest/hookspec.py diff --git a/lib/spack/external/_pytest/junitxml.py b/lib/spack/external/pytest-fallback/_pytest/junitxml.py similarity index 100% rename from lib/spack/external/_pytest/junitxml.py rename to lib/spack/external/pytest-fallback/_pytest/junitxml.py diff --git a/lib/spack/external/_pytest/main.py b/lib/spack/external/pytest-fallback/_pytest/main.py similarity index 100% rename from lib/spack/external/_pytest/main.py rename to lib/spack/external/pytest-fallback/_pytest/main.py diff --git a/lib/spack/external/_pytest/mark.py b/lib/spack/external/pytest-fallback/_pytest/mark.py similarity index 100% rename from lib/spack/external/_pytest/mark.py rename to lib/spack/external/pytest-fallback/_pytest/mark.py diff --git a/lib/spack/external/_pytest/monkeypatch.py b/lib/spack/external/pytest-fallback/_pytest/monkeypatch.py similarity index 100% rename from lib/spack/external/_pytest/monkeypatch.py rename to lib/spack/external/pytest-fallback/_pytest/monkeypatch.py diff --git a/lib/spack/external/_pytest/nodes.py b/lib/spack/external/pytest-fallback/_pytest/nodes.py similarity index 100% rename from lib/spack/external/_pytest/nodes.py rename to lib/spack/external/pytest-fallback/_pytest/nodes.py diff --git a/lib/spack/external/_pytest/nose.py b/lib/spack/external/pytest-fallback/_pytest/nose.py similarity index 100% rename from lib/spack/external/_pytest/nose.py rename to lib/spack/external/pytest-fallback/_pytest/nose.py diff --git a/lib/spack/external/_pytest/outcomes.py b/lib/spack/external/pytest-fallback/_pytest/outcomes.py similarity index 100% rename from lib/spack/external/_pytest/outcomes.py rename to lib/spack/external/pytest-fallback/_pytest/outcomes.py diff --git a/lib/spack/external/_pytest/pastebin.py b/lib/spack/external/pytest-fallback/_pytest/pastebin.py similarity index 100% rename from lib/spack/external/_pytest/pastebin.py rename to lib/spack/external/pytest-fallback/_pytest/pastebin.py diff --git a/lib/spack/external/_pytest/pytester.py b/lib/spack/external/pytest-fallback/_pytest/pytester.py similarity index 100% rename from lib/spack/external/_pytest/pytester.py rename to lib/spack/external/pytest-fallback/_pytest/pytester.py diff --git a/lib/spack/external/_pytest/python.py b/lib/spack/external/pytest-fallback/_pytest/python.py similarity index 100% rename from lib/spack/external/_pytest/python.py rename to lib/spack/external/pytest-fallback/_pytest/python.py diff --git a/lib/spack/external/_pytest/python_api.py b/lib/spack/external/pytest-fallback/_pytest/python_api.py similarity index 100% rename from lib/spack/external/_pytest/python_api.py rename to lib/spack/external/pytest-fallback/_pytest/python_api.py diff --git a/lib/spack/external/_pytest/recwarn.py b/lib/spack/external/pytest-fallback/_pytest/recwarn.py similarity index 100% rename from lib/spack/external/_pytest/recwarn.py rename to lib/spack/external/pytest-fallback/_pytest/recwarn.py diff --git a/lib/spack/external/_pytest/resultlog.py b/lib/spack/external/pytest-fallback/_pytest/resultlog.py similarity index 100% rename from lib/spack/external/_pytest/resultlog.py rename to lib/spack/external/pytest-fallback/_pytest/resultlog.py diff --git a/lib/spack/external/_pytest/runner.py b/lib/spack/external/pytest-fallback/_pytest/runner.py similarity index 100% rename from lib/spack/external/_pytest/runner.py rename to lib/spack/external/pytest-fallback/_pytest/runner.py diff --git a/lib/spack/external/_pytest/setuponly.py b/lib/spack/external/pytest-fallback/_pytest/setuponly.py similarity index 100% rename from lib/spack/external/_pytest/setuponly.py rename to lib/spack/external/pytest-fallback/_pytest/setuponly.py diff --git a/lib/spack/external/_pytest/setupplan.py b/lib/spack/external/pytest-fallback/_pytest/setupplan.py similarity index 100% rename from lib/spack/external/_pytest/setupplan.py rename to lib/spack/external/pytest-fallback/_pytest/setupplan.py diff --git a/lib/spack/external/_pytest/skipping.py b/lib/spack/external/pytest-fallback/_pytest/skipping.py similarity index 100% rename from lib/spack/external/_pytest/skipping.py rename to lib/spack/external/pytest-fallback/_pytest/skipping.py diff --git a/lib/spack/external/_pytest/terminal.py b/lib/spack/external/pytest-fallback/_pytest/terminal.py similarity index 100% rename from lib/spack/external/_pytest/terminal.py rename to lib/spack/external/pytest-fallback/_pytest/terminal.py diff --git a/lib/spack/external/_pytest/tmpdir.py b/lib/spack/external/pytest-fallback/_pytest/tmpdir.py similarity index 100% rename from lib/spack/external/_pytest/tmpdir.py rename to lib/spack/external/pytest-fallback/_pytest/tmpdir.py diff --git a/lib/spack/external/_pytest/unittest.py b/lib/spack/external/pytest-fallback/_pytest/unittest.py similarity index 100% rename from lib/spack/external/_pytest/unittest.py rename to lib/spack/external/pytest-fallback/_pytest/unittest.py diff --git a/lib/spack/external/_pytest/vendored_packages/README.md b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/README.md similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/README.md rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/README.md diff --git a/lib/spack/external/_pytest/vendored_packages/__init__.py b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/__init__.py similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/__init__.py rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/__init__.py diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/DESCRIPTION.rst b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/DESCRIPTION.rst similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/DESCRIPTION.rst rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/DESCRIPTION.rst diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/INSTALLER b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/INSTALLER similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/INSTALLER rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/INSTALLER diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/LICENSE.txt b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/LICENSE.txt similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/LICENSE.txt rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/LICENSE.txt diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/METADATA b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/METADATA similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/METADATA rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/METADATA diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/RECORD b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/RECORD similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/RECORD rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/RECORD diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/WHEEL b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/WHEEL similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/WHEEL rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/WHEEL diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/metadata.json b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/metadata.json similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/metadata.json rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/metadata.json diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/top_level.txt b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/top_level.txt similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy-0.4.0.dist-info/top_level.txt rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy-0.4.0.dist-info/top_level.txt diff --git a/lib/spack/external/_pytest/vendored_packages/pluggy.py b/lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy.py similarity index 100% rename from lib/spack/external/_pytest/vendored_packages/pluggy.py rename to lib/spack/external/pytest-fallback/_pytest/vendored_packages/pluggy.py diff --git a/lib/spack/external/_pytest/warnings.py b/lib/spack/external/pytest-fallback/_pytest/warnings.py similarity index 100% rename from lib/spack/external/_pytest/warnings.py rename to lib/spack/external/pytest-fallback/_pytest/warnings.py diff --git a/lib/spack/external/py/__init__.py b/lib/spack/external/pytest-fallback/py/__init__.py similarity index 100% rename from lib/spack/external/py/__init__.py rename to lib/spack/external/pytest-fallback/py/__init__.py diff --git a/lib/spack/external/py/__metainfo.py b/lib/spack/external/pytest-fallback/py/__metainfo.py similarity index 100% rename from lib/spack/external/py/__metainfo.py rename to lib/spack/external/pytest-fallback/py/__metainfo.py diff --git a/lib/spack/external/py/_apipkg.py b/lib/spack/external/pytest-fallback/py/_apipkg.py similarity index 100% rename from lib/spack/external/py/_apipkg.py rename to lib/spack/external/pytest-fallback/py/_apipkg.py diff --git a/lib/spack/external/py/_builtin.py b/lib/spack/external/pytest-fallback/py/_builtin.py similarity index 100% rename from lib/spack/external/py/_builtin.py rename to lib/spack/external/pytest-fallback/py/_builtin.py diff --git a/lib/spack/external/py/_code/__init__.py b/lib/spack/external/pytest-fallback/py/_code/__init__.py similarity index 100% rename from lib/spack/external/py/_code/__init__.py rename to lib/spack/external/pytest-fallback/py/_code/__init__.py diff --git a/lib/spack/external/py/_code/_assertionnew.py b/lib/spack/external/pytest-fallback/py/_code/_assertionnew.py similarity index 100% rename from lib/spack/external/py/_code/_assertionnew.py rename to lib/spack/external/pytest-fallback/py/_code/_assertionnew.py diff --git a/lib/spack/external/py/_code/_assertionold.py b/lib/spack/external/pytest-fallback/py/_code/_assertionold.py similarity index 100% rename from lib/spack/external/py/_code/_assertionold.py rename to lib/spack/external/pytest-fallback/py/_code/_assertionold.py diff --git a/lib/spack/external/py/_code/_py2traceback.py b/lib/spack/external/pytest-fallback/py/_code/_py2traceback.py similarity index 100% rename from lib/spack/external/py/_code/_py2traceback.py rename to lib/spack/external/pytest-fallback/py/_code/_py2traceback.py diff --git a/lib/spack/external/py/_code/assertion.py b/lib/spack/external/pytest-fallback/py/_code/assertion.py similarity index 100% rename from lib/spack/external/py/_code/assertion.py rename to lib/spack/external/pytest-fallback/py/_code/assertion.py diff --git a/lib/spack/external/py/_code/code.py b/lib/spack/external/pytest-fallback/py/_code/code.py similarity index 100% rename from lib/spack/external/py/_code/code.py rename to lib/spack/external/pytest-fallback/py/_code/code.py diff --git a/lib/spack/external/py/_code/source.py b/lib/spack/external/pytest-fallback/py/_code/source.py similarity index 100% rename from lib/spack/external/py/_code/source.py rename to lib/spack/external/pytest-fallback/py/_code/source.py diff --git a/lib/spack/external/py/_error.py b/lib/spack/external/pytest-fallback/py/_error.py similarity index 100% rename from lib/spack/external/py/_error.py rename to lib/spack/external/pytest-fallback/py/_error.py diff --git a/lib/spack/external/py/_iniconfig.py b/lib/spack/external/pytest-fallback/py/_iniconfig.py similarity index 100% rename from lib/spack/external/py/_iniconfig.py rename to lib/spack/external/pytest-fallback/py/_iniconfig.py diff --git a/lib/spack/external/py/_io/__init__.py b/lib/spack/external/pytest-fallback/py/_io/__init__.py similarity index 100% rename from lib/spack/external/py/_io/__init__.py rename to lib/spack/external/pytest-fallback/py/_io/__init__.py diff --git a/lib/spack/external/py/_io/capture.py b/lib/spack/external/pytest-fallback/py/_io/capture.py similarity index 100% rename from lib/spack/external/py/_io/capture.py rename to lib/spack/external/pytest-fallback/py/_io/capture.py diff --git a/lib/spack/external/py/_io/saferepr.py b/lib/spack/external/pytest-fallback/py/_io/saferepr.py similarity index 100% rename from lib/spack/external/py/_io/saferepr.py rename to lib/spack/external/pytest-fallback/py/_io/saferepr.py diff --git a/lib/spack/external/py/_io/terminalwriter.py b/lib/spack/external/pytest-fallback/py/_io/terminalwriter.py similarity index 100% rename from lib/spack/external/py/_io/terminalwriter.py rename to lib/spack/external/pytest-fallback/py/_io/terminalwriter.py diff --git a/lib/spack/external/py/_log/__init__.py b/lib/spack/external/pytest-fallback/py/_log/__init__.py similarity index 100% rename from lib/spack/external/py/_log/__init__.py rename to lib/spack/external/pytest-fallback/py/_log/__init__.py diff --git a/lib/spack/external/py/_log/log.py b/lib/spack/external/pytest-fallback/py/_log/log.py similarity index 100% rename from lib/spack/external/py/_log/log.py rename to lib/spack/external/pytest-fallback/py/_log/log.py diff --git a/lib/spack/external/py/_log/warning.py b/lib/spack/external/pytest-fallback/py/_log/warning.py similarity index 100% rename from lib/spack/external/py/_log/warning.py rename to lib/spack/external/pytest-fallback/py/_log/warning.py diff --git a/lib/spack/external/py/_path/__init__.py b/lib/spack/external/pytest-fallback/py/_path/__init__.py similarity index 100% rename from lib/spack/external/py/_path/__init__.py rename to lib/spack/external/pytest-fallback/py/_path/__init__.py diff --git a/lib/spack/external/py/_path/cacheutil.py b/lib/spack/external/pytest-fallback/py/_path/cacheutil.py similarity index 100% rename from lib/spack/external/py/_path/cacheutil.py rename to lib/spack/external/pytest-fallback/py/_path/cacheutil.py diff --git a/lib/spack/external/py/_path/common.py b/lib/spack/external/pytest-fallback/py/_path/common.py similarity index 100% rename from lib/spack/external/py/_path/common.py rename to lib/spack/external/pytest-fallback/py/_path/common.py diff --git a/lib/spack/external/py/_path/local.py b/lib/spack/external/pytest-fallback/py/_path/local.py similarity index 100% rename from lib/spack/external/py/_path/local.py rename to lib/spack/external/pytest-fallback/py/_path/local.py diff --git a/lib/spack/external/py/_path/svnurl.py b/lib/spack/external/pytest-fallback/py/_path/svnurl.py similarity index 100% rename from lib/spack/external/py/_path/svnurl.py rename to lib/spack/external/pytest-fallback/py/_path/svnurl.py diff --git a/lib/spack/external/py/_path/svnwc.py b/lib/spack/external/pytest-fallback/py/_path/svnwc.py similarity index 100% rename from lib/spack/external/py/_path/svnwc.py rename to lib/spack/external/pytest-fallback/py/_path/svnwc.py diff --git a/lib/spack/external/py/_process/__init__.py b/lib/spack/external/pytest-fallback/py/_process/__init__.py similarity index 100% rename from lib/spack/external/py/_process/__init__.py rename to lib/spack/external/pytest-fallback/py/_process/__init__.py diff --git a/lib/spack/external/py/_process/cmdexec.py b/lib/spack/external/pytest-fallback/py/_process/cmdexec.py similarity index 100% rename from lib/spack/external/py/_process/cmdexec.py rename to lib/spack/external/pytest-fallback/py/_process/cmdexec.py diff --git a/lib/spack/external/py/_process/forkedfunc.py b/lib/spack/external/pytest-fallback/py/_process/forkedfunc.py similarity index 100% rename from lib/spack/external/py/_process/forkedfunc.py rename to lib/spack/external/pytest-fallback/py/_process/forkedfunc.py diff --git a/lib/spack/external/py/_process/killproc.py b/lib/spack/external/pytest-fallback/py/_process/killproc.py similarity index 100% rename from lib/spack/external/py/_process/killproc.py rename to lib/spack/external/pytest-fallback/py/_process/killproc.py diff --git a/lib/spack/external/py/_std.py b/lib/spack/external/pytest-fallback/py/_std.py similarity index 100% rename from lib/spack/external/py/_std.py rename to lib/spack/external/pytest-fallback/py/_std.py diff --git a/lib/spack/external/py/_xmlgen.py b/lib/spack/external/pytest-fallback/py/_xmlgen.py similarity index 100% rename from lib/spack/external/py/_xmlgen.py rename to lib/spack/external/pytest-fallback/py/_xmlgen.py diff --git a/lib/spack/external/py/test.py b/lib/spack/external/pytest-fallback/py/test.py similarity index 100% rename from lib/spack/external/py/test.py rename to lib/spack/external/pytest-fallback/py/test.py diff --git a/lib/spack/external/pytest.py b/lib/spack/external/pytest-fallback/pytest.py similarity index 100% rename from lib/spack/external/pytest.py rename to lib/spack/external/pytest-fallback/pytest.py diff --git a/lib/spack/spack/cmd/unit_test.py b/lib/spack/spack/cmd/unit_test.py index ce4e2cbdbb4..0f117f2d7ad 100644 --- a/lib/spack/spack/cmd/unit_test.py +++ b/lib/spack/spack/cmd/unit_test.py @@ -7,14 +7,19 @@ import argparse import collections +import os.path import re import sys -import pytest +try: + import pytest +except ImportError: + pytest = None # type: ignore + from six import StringIO +import llnl.util.filesystem import llnl.util.tty.color as color -from llnl.util.filesystem import working_dir from llnl.util.tty.colify import colify import spack.paths @@ -67,38 +72,6 @@ def setup_parser(subparser): def do_list(args, extra_args): """Print a lists of tests than what pytest offers.""" - # Run test collection and get the tree out. - old_output = sys.stdout - try: - sys.stdout = output = StringIO() - pytest.main(['--collect-only'] + extra_args) - finally: - sys.stdout = old_output - - lines = output.getvalue().split('\n') - tests = collections.defaultdict(lambda: set()) - prefix = [] - - # collect tests into sections - for line in lines: - match = re.match(r"(\s*)<([^ ]*) '([^']*)'", line) - if not match: - continue - indent, nodetype, name = match.groups() - - # strip parametrized tests - if "[" in name: - name = name[:name.index("[")] - - depth = len(indent) // 2 - - if nodetype.endswith("Function"): - key = tuple(prefix) - tests[key].add(name) - else: - prefix = prefix[:depth] - prefix.append(name) - def colorize(c, prefix): if isinstance(prefix, tuple): return "::".join( @@ -107,8 +80,65 @@ def colorize(c, prefix): ) return color.colorize("@%s{%s}" % (c, prefix)) + # To list the files we just need to inspect the filesystem, + # which doesn't need to wait for pytest collection and doesn't + # require parsing pytest output + files = llnl.util.filesystem.find( + root=spack.paths.test_path, files='*.py', recursive=True + ) + files = [ + os.path.relpath(f, start=spack.paths.spack_root) + for f in files if not f.endswith(('conftest.py', '__init__.py')) + ] + + old_output = sys.stdout + try: + sys.stdout = output = StringIO() + pytest.main(['--collect-only'] + extra_args) + finally: + sys.stdout = old_output + + lines = output.getvalue().split('\n') + tests = collections.defaultdict(set) + + # collect tests into sections + node_regexp = re.compile(r"(\s*)<([^ ]*) ['\"]?([^']*)['\"]?>") + key_parts, name_parts = [], [] + for line in lines: + match = node_regexp.match(line) + if not match: + continue + indent, nodetype, name = match.groups() + + # strip parametrized tests + if "[" in name: + name = name[:name.index("[")] + + len_indent = len(indent) + if os.path.isabs(name): + name = os.path.relpath(name, start=spack.paths.spack_root) + + item = (len_indent, name, nodetype) + + # Reduce the parts to the scopes that are of interest + name_parts = [x for x in name_parts if x[0] < len_indent] + key_parts = [x for x in key_parts if x[0] < len_indent] + + # From version 3.X to version 6.X the output format + # changed a lot in pytest, and probably will change + # in the future - so this manipulation might be fragile + if nodetype.lower() == 'function': + name_parts.append(item) + key_end = os.path.join(*[x[1] for x in key_parts]) + key = next(f for f in files if f.endswith(key_end)) + tests[key].add(tuple(x[1] for x in name_parts)) + elif nodetype.lower() == 'class': + name_parts.append(item) + elif nodetype.lower() in ('package', 'module'): + key_parts.append(item) + if args.list == "list": - files = set(prefix[0] for prefix in tests) + files = set(tests.keys()) color_files = [colorize("B", file) for file in sorted(files)] colify(color_files) @@ -144,6 +174,14 @@ def add_back_pytest_args(args, unknown_args): def unit_test(parser, args, unknown_args): + global pytest + if pytest is None: + vendored_pytest_dir = os.path.join( + spack.paths.external_path, 'pytest-fallback' + ) + sys.path.append(vendored_pytest_dir) + import pytest + if args.pytest_help: # make the pytest.main help output more accurate sys.argv[0] = 'spack unit-test' @@ -161,7 +199,7 @@ def unit_test(parser, args, unknown_args): pytest_root = spack.extensions.path_for_extension(target, *extensions) # pytest.ini lives in the root of the spack repository. - with working_dir(pytest_root): + with llnl.util.filesystem.working_dir(pytest_root): if args.list: do_list(args, pytest_args) return diff --git a/lib/spack/spack/test/cmd/unit_test.py b/lib/spack/spack/test/cmd/unit_test.py index 1a273ff2443..9811bdbfbd2 100644 --- a/lib/spack/spack/test/cmd/unit_test.py +++ b/lib/spack/spack/test/cmd/unit_test.py @@ -22,7 +22,10 @@ def test_list_with_pytest_arg(): def test_list_with_keywords(): - output = spack_test('--list', '-k', 'cmd/unit_test.py') + # Here we removed querying with a "/" to separate directories + # since the behavior is inconsistent across different pytest + # versions, see https://stackoverflow.com/a/48814787/771663 + output = spack_test('--list', '-k', 'unit_test.py') assert output.strip() == cmd_test_py diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py index 9a6dc0b13be..d502cf1db19 100644 --- a/lib/spack/spack/test/conftest.py +++ b/lib/spack/spack/test/conftest.py @@ -430,8 +430,14 @@ def _skip_if_missing_executables(request): """Permits to mark tests with 'require_executables' and skip the tests if the executables passed as arguments are not found. """ - if request.node.get_marker('requires_executables'): - required_execs = request.node.get_marker('requires_executables').args + if hasattr(request.node, 'get_marker'): + # TODO: Remove the deprecated API as soon as we drop support for Python 2.6 + marker = request.node.get_marker('requires_executables') + else: + marker = request.node.get_closest_marker('requires_executables') + + if marker: + required_execs = marker.args missing_execs = [ x for x in required_execs if spack.util.executable.which(x) is None ] @@ -1453,7 +1459,7 @@ def invalid_spec(request): return request.param -@pytest.fixture("module") +@pytest.fixture(scope='module') def mock_test_repo(tmpdir_factory): """Create an empty repository.""" repo_namespace = 'mock_test_repo'