summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Clay <mclay@redhat.com>2021-11-16 18:16:42 -0800
committerGitHub <noreply@github.com>2021-11-16 18:16:42 -0800
commitbb63c97c162040548f1d9e684a6e35c403a03f4c (patch)
tree91720bda5158d24b29fa56fa3f1b9da4d7d1f378
parent21ac52435bf1cba75678ccf5c4c6638d99bd4bae (diff)
downloadansible-bb63c97c162040548f1d9e684a6e35c403a03f4c.tar.gz
ansible-test - Update import test and sanity requirements. (#76308)
* Add script to freeze sanity requirements. * Declare sanity test requirements and freeze * Use pinned requirements for import.plugin test. * Expand scope of import test for ansible-core. * Add ignores for galaxy import errors. * Update test-constraints sanity test.
-rw-r--r--MANIFEST.in5
-rw-r--r--changelogs/fragments/ansible-test-sanity-requirements-update.yaml4
-rw-r--r--docs/docsite/rst/dev_guide/testing/sanity/import.rst10
-rwxr-xr-xhacking/update-sanity-requirements.py112
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.ansible-doc.in3
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.ansible-doc.txt13
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.changelog.in2
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.changelog.txt17
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.import.in1
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.import.plugin.in2
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.import.plugin.txt4
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.import.txt3
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.integration-aliases.in1
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.integration-aliases.txt3
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.pep8.in1
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.pep8.txt3
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.pylint.in2
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.pylint.txt19
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.in2
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.txt5
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.validate-modules.in3
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.validate-modules.txt11
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.yamllint.in1
-rw-r--r--test/lib/ansible_test/_data/requirements/sanity.yamllint.txt9
-rw-r--r--test/lib/ansible_test/_internal/commands/sanity/__init__.py12
-rw-r--r--test/lib/ansible_test/_internal/commands/sanity/import.py21
-rw-r--r--test/sanity/code-smell/botmeta.requirements.in2
-rw-r--r--test/sanity/code-smell/botmeta.requirements.txt5
-rw-r--r--test/sanity/code-smell/deprecated-config.requirements.in2
-rw-r--r--test/sanity/code-smell/deprecated-config.requirements.txt9
-rw-r--r--test/sanity/code-smell/docs-build.requirements.in8
-rw-r--r--test/sanity/code-smell/docs-build.requirements.txt100
-rw-r--r--test/sanity/code-smell/package-data.requirements.in7
-rw-r--r--test/sanity/code-smell/package-data.requirements.txt25
-rw-r--r--test/sanity/code-smell/release-names.requirements.in1
-rw-r--r--test/sanity/code-smell/release-names.requirements.txt3
-rw-r--r--test/sanity/code-smell/rstcheck.requirements.in3
-rw-r--r--test/sanity/code-smell/rstcheck.requirements.txt52
-rw-r--r--test/sanity/code-smell/test-constraints.py29
-rw-r--r--test/sanity/code-smell/update-bundled.requirements.in1
-rw-r--r--test/sanity/code-smell/update-bundled.requirements.txt7
-rw-r--r--test/sanity/ignore.txt33
42 files changed, 380 insertions, 176 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index 22c8ce8678..e75acb70cd 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -29,10 +29,10 @@ recursive-include packaging *
recursive-include test/ansible_test *.py Makefile
recursive-include test/integration *
recursive-include test/lib/ansible_test/config *.yml *.template
-recursive-include test/lib/ansible_test/_data *.cfg *.ini *.ps1 *.txt *.yml coveragerc
+recursive-include test/lib/ansible_test/_data *.cfg *.in *.ini *.ps1 *.txt *.yml coveragerc
recursive-include test/lib/ansible_test/_util *.cfg *.json *.ps1 *.psd1 *.py *.sh *.txt *.yml
recursive-include test/lib/ansible_test/_util/controller/sanity/validate-modules validate-modules
-recursive-include test/sanity *.json *.py *.txt
+recursive-include test/sanity *.in *.json *.py *.txt
recursive-include test/support *.py *.ps1 *.psm1 *.cs
exclude test/sanity/code-smell/botmeta.*
exclude test/sanity/code-smell/release-names.*
@@ -46,4 +46,5 @@ include changelogs/changelog.yaml
recursive-include hacking/build_library *.py
include hacking/build-ansible.py
include hacking/test-module.py
+include hacking/update-sanity-requirements.py
include bin/*
diff --git a/changelogs/fragments/ansible-test-sanity-requirements-update.yaml b/changelogs/fragments/ansible-test-sanity-requirements-update.yaml
new file mode 100644
index 0000000000..4499b85e2a
--- /dev/null
+++ b/changelogs/fragments/ansible-test-sanity-requirements-update.yaml
@@ -0,0 +1,4 @@
+minor_changes:
+ - ansible-test - Declare public dependencies of ansible-core and use to limit unguarded imports in plugins.
+ - ansible-test - Requirements for the plugin import test are now frozen.
+ - ansible-test - Update sanity test requirements.
diff --git a/docs/docsite/rst/dev_guide/testing/sanity/import.rst b/docs/docsite/rst/dev_guide/testing/sanity/import.rst
index 045afee718..49994092c7 100644
--- a/docs/docsite/rst/dev_guide/testing/sanity/import.rst
+++ b/docs/docsite/rst/dev_guide/testing/sanity/import.rst
@@ -60,9 +60,15 @@ Ansible allows the following unchecked imports from these specific directories:
* ansible-core:
* For ``lib/ansible/modules/`` and ``lib/ansible/module_utils/``, unchecked imports are only allowed from the Python standard library;
- * For ``lib/ansible/plugins/``, unchecked imports are only allowed from the Python standard library, from dependencies of ansible-core, and from ansible-core itself;
+ * For ``lib/ansible/plugins/``, unchecked imports are only allowed from the Python standard library, from public dependencies of ansible-core, and from ansible-core itself;
* collections:
* For ``plugins/modules/`` and ``plugins/module_utils/``, unchecked imports are only allowed from the Python standard library;
- * For other directories in ``plugins/`` (see `the community collection requirements <https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#modules-plugins>`_ for a list), unchecked imports are only allowed from the Python standard library, from dependencies of ansible-core, and from ansible-core itself.
+ * For other directories in ``plugins/`` (see `the community collection requirements <https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#modules-plugins>`_ for a list), unchecked imports are only allowed from the Python standard library, from public dependencies of ansible-core, and from ansible-core itself.
+
+Public dependencies of ansible-core are:
+
+ * Jinja2
+ * PyYAML
+ * MarkupSafe (as a dependency of Jinja2)
diff --git a/hacking/update-sanity-requirements.py b/hacking/update-sanity-requirements.py
new file mode 100755
index 0000000000..747f058880
--- /dev/null
+++ b/hacking/update-sanity-requirements.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+# PYTHON_ARGCOMPLETE_OK
+"""Generate frozen sanity test requirements from source requirements files."""
+
+from __future__ import annotations
+
+import argparse
+import dataclasses
+import pathlib
+import subprocess
+import tempfile
+import typing as t
+import venv
+
+try:
+ import argcomplete
+except ImportError:
+ argcomplete = None
+
+
+FILE = pathlib.Path(__file__).resolve()
+ROOT = FILE.parent.parent
+SELF = FILE.relative_to(ROOT)
+
+
+@dataclasses.dataclass(frozen=True)
+class SanityTest:
+ name: str
+ requirements_path: pathlib.Path
+ source_path: pathlib.Path
+
+ def freeze_requirements(self) -> None:
+ with tempfile.TemporaryDirectory() as venv_dir:
+ venv.create(venv_dir, with_pip=True)
+
+ python = pathlib.Path(venv_dir, 'bin', 'python')
+ pip = [python, '-m', 'pip', '--disable-pip-version-check']
+ env = dict()
+
+ pip_freeze = subprocess.run(pip + ['freeze'], env=env, check=True, capture_output=True, text=True)
+
+ if pip_freeze.stdout:
+ raise Exception(f'Initial virtual environment is not empty:\n{pip_freeze.stdout}')
+
+ subprocess.run(pip + ['install', 'wheel'], env=env, check=True) # make bdist_wheel available during pip install
+ subprocess.run(pip + ['install', '-r', self.source_path], env=env, check=True)
+
+ pip_freeze = subprocess.run(pip + ['freeze'], env=env, check=True, capture_output=True, text=True)
+
+ requirements = f'# edit "{self.source_path.name}" and generate with: {SELF} --test {self.name}\n{pip_freeze.stdout}'
+
+ with open(self.requirements_path, 'w') as requirement_file:
+ requirement_file.write(requirements)
+
+ @staticmethod
+ def create(path: pathlib.Path) -> SanityTest:
+ return SanityTest(
+ name=path.stem.replace('sanity.', '').replace('.requirements', ''),
+ requirements_path=path,
+ source_path=path.with_suffix('.in'),
+ )
+
+
+def main() -> None:
+ tests = find_tests()
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--test',
+ metavar='TEST',
+ dest='test_names',
+ action='append',
+ choices=[test.name for test in tests],
+ help='test requirements to update'
+ )
+
+ if argcomplete:
+ argcomplete.autocomplete(parser)
+
+ args = parser.parse_args()
+ test_names: set[str] = set(args.test_names or [])
+
+ tests = [test for test in tests if test.name in test_names] if test_names else tests
+
+ for test in tests:
+ print(f'===[ {test.name} ]===')
+ test.freeze_requirements()
+
+
+def find_tests() -> t.List[SanityTest]:
+ globs = (
+ 'test/lib/ansible_test/_data/requirements/sanity.*.txt',
+ 'test/sanity/code-smell/*.requirements.txt',
+ )
+
+ tests: t.List[SanityTest] = []
+
+ for glob in globs:
+ tests.extend(get_tests(pathlib.Path(glob)))
+
+ return sorted(tests, key=lambda test: test.name)
+
+
+def get_tests(glob: pathlib.Path) -> t.List[SanityTest]:
+ path = pathlib.Path(ROOT, glob.parent)
+ pattern = glob.name
+
+ return [SanityTest.create(item) for item in path.glob(pattern)]
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/lib/ansible_test/_data/requirements/sanity.ansible-doc.in b/test/lib/ansible_test/_data/requirements/sanity.ansible-doc.in
new file mode 100644
index 0000000000..80c769fbb3
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.ansible-doc.in
@@ -0,0 +1,3 @@
+jinja2 # ansible-core requirement
+packaging # ansible-core requirement
+pyyaml # ansible-core requirement
diff --git a/test/lib/ansible_test/_data/requirements/sanity.ansible-doc.txt b/test/lib/ansible_test/_data/requirements/sanity.ansible-doc.txt
index 660620dc7b..105069f2e3 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.ansible-doc.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.ansible-doc.txt
@@ -1,7 +1,6 @@
-jinja2 == 3.0.1 # ansible-core requirement
-pyyaml == 5.4.1 # ansible-core requirement
-packaging == 21.0 # ansible-doc requirement
-
-# dependencies
-MarkupSafe == 2.0.1
-pyparsing == 2.4.7
+# edit "sanity.ansible-doc.in" and generate with: hacking/update-sanity-requirements.py --test ansible-doc
+Jinja2==3.0.3
+MarkupSafe==2.0.1
+packaging==21.2
+pyparsing==2.4.7
+PyYAML==6.0
diff --git a/test/lib/ansible_test/_data/requirements/sanity.changelog.in b/test/lib/ansible_test/_data/requirements/sanity.changelog.in
new file mode 100644
index 0000000000..3fcfbe0841
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.changelog.in
@@ -0,0 +1,2 @@
+antsibull-changelog
+docutils < 0.18 # match version required by sphinx in the docs-build sanity test
diff --git a/test/lib/ansible_test/_data/requirements/sanity.changelog.txt b/test/lib/ansible_test/_data/requirements/sanity.changelog.txt
index cb9f02f873..b378b5f375 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.changelog.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.changelog.txt
@@ -1,9 +1,8 @@
-antsibull-changelog == 0.9.0
-
-# dependencies
-pyyaml == 5.4.1
-docutils == 0.17.1
-packaging == 21.0
-pyparsing == 2.4.7
-rstcheck == 3.3.1
-semantic-version == 2.8.5
+# edit "sanity.changelog.in" and generate with: hacking/update-sanity-requirements.py --test changelog
+antsibull-changelog==0.12.0
+docutils==0.17.1
+packaging==21.2
+pyparsing==2.4.7
+PyYAML==6.0
+rstcheck==3.3.1
+semantic-version==2.8.5
diff --git a/test/lib/ansible_test/_data/requirements/sanity.import.in b/test/lib/ansible_test/_data/requirements/sanity.import.in
new file mode 100644
index 0000000000..dea704eb04
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.import.in
@@ -0,0 +1 @@
+pyyaml # needed for yaml_to_json.py
diff --git a/test/lib/ansible_test/_data/requirements/sanity.import.plugin.in b/test/lib/ansible_test/_data/requirements/sanity.import.plugin.in
new file mode 100644
index 0000000000..cec0eed3cd
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.import.plugin.in
@@ -0,0 +1,2 @@
+jinja2 # ansible-core requirement
+pyyaml # ansible-core requirement
diff --git a/test/lib/ansible_test/_data/requirements/sanity.import.plugin.txt b/test/lib/ansible_test/_data/requirements/sanity.import.plugin.txt
new file mode 100644
index 0000000000..bf7050ddea
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.import.plugin.txt
@@ -0,0 +1,4 @@
+# edit "sanity.import.plugin.in" and generate with: hacking/update-sanity-requirements.py --test import.plugin
+Jinja2==3.0.3
+MarkupSafe==2.0.1
+PyYAML==6.0
diff --git a/test/lib/ansible_test/_data/requirements/sanity.import.txt b/test/lib/ansible_test/_data/requirements/sanity.import.txt
index d77a09d7f5..e9645ea2da 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.import.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.import.txt
@@ -1 +1,2 @@
-pyyaml == 5.4.1 # needed for yaml_to_json.py
+# edit "sanity.import.in" and generate with: hacking/update-sanity-requirements.py --test import
+PyYAML==6.0
diff --git a/test/lib/ansible_test/_data/requirements/sanity.integration-aliases.in b/test/lib/ansible_test/_data/requirements/sanity.integration-aliases.in
new file mode 100644
index 0000000000..c3726e8bfe
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.integration-aliases.in
@@ -0,0 +1 @@
+pyyaml
diff --git a/test/lib/ansible_test/_data/requirements/sanity.integration-aliases.txt b/test/lib/ansible_test/_data/requirements/sanity.integration-aliases.txt
index cc530e42c2..ba3a50284f 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.integration-aliases.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.integration-aliases.txt
@@ -1 +1,2 @@
-pyyaml == 5.4.1
+# edit "sanity.integration-aliases.in" and generate with: hacking/update-sanity-requirements.py --test integration-aliases
+PyYAML==6.0
diff --git a/test/lib/ansible_test/_data/requirements/sanity.pep8.in b/test/lib/ansible_test/_data/requirements/sanity.pep8.in
new file mode 100644
index 0000000000..282a93fbd7
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.pep8.in
@@ -0,0 +1 @@
+pycodestyle
diff --git a/test/lib/ansible_test/_data/requirements/sanity.pep8.txt b/test/lib/ansible_test/_data/requirements/sanity.pep8.txt
index 86f73fba11..cc0f1afd4f 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.pep8.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.pep8.txt
@@ -1 +1,2 @@
-pycodestyle == 2.6.0
+# edit "sanity.pep8.in" and generate with: hacking/update-sanity-requirements.py --test pep8
+pycodestyle==2.8.0
diff --git a/test/lib/ansible_test/_data/requirements/sanity.pylint.in b/test/lib/ansible_test/_data/requirements/sanity.pylint.in
new file mode 100644
index 0000000000..2344fb4d35
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.pylint.in
@@ -0,0 +1,2 @@
+pylint == 2.9.3 # currently vetted version
+pyyaml # needed for collection_detail.py
diff --git a/test/lib/ansible_test/_data/requirements/sanity.pylint.txt b/test/lib/ansible_test/_data/requirements/sanity.pylint.txt
index 7332d16238..85fdedb846 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.pylint.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.pylint.txt
@@ -1,10 +1,9 @@
-pylint == 2.9.3
-pyyaml == 5.4.1 # needed for collection_detail.py
-
-# dependencies
-astroid == 2.6.6
-isort == 5.9.3
-lazy-object-proxy == 1.6.0
-mccabe == 0.6.1
-toml == 0.10.2
-wrapt == 1.12.1
+# edit "sanity.pylint.in" and generate with: hacking/update-sanity-requirements.py --test pylint
+astroid==2.6.6
+isort==5.10.1
+lazy-object-proxy==1.6.0
+mccabe==0.6.1
+pylint==2.9.3
+PyYAML==6.0
+toml==0.10.2
+wrapt==1.12.1
diff --git a/test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.in b/test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.in
new file mode 100644
index 0000000000..edd96991dd
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.in
@@ -0,0 +1,2 @@
+pyyaml
+voluptuous
diff --git a/test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.txt b/test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.txt
index 1281a04528..3324a38955 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.runtime-metadata.txt
@@ -1,2 +1,3 @@
-pyyaml == 5.4.1
-voluptuous == 0.12.1
+# edit "sanity.runtime-metadata.in" and generate with: hacking/update-sanity-requirements.py --test runtime-metadata
+PyYAML==6.0
+voluptuous==0.12.2
diff --git a/test/lib/ansible_test/_data/requirements/sanity.validate-modules.in b/test/lib/ansible_test/_data/requirements/sanity.validate-modules.in
new file mode 100644
index 0000000000..efe940041c
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.validate-modules.in
@@ -0,0 +1,3 @@
+jinja2 # ansible-core requirement
+pyyaml # needed for collection_detail.py
+voluptuous
diff --git a/test/lib/ansible_test/_data/requirements/sanity.validate-modules.txt b/test/lib/ansible_test/_data/requirements/sanity.validate-modules.txt
index 4b1d5f05d0..32f14fea85 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.validate-modules.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.validate-modules.txt
@@ -1,6 +1,5 @@
-jinja2 == 3.0.1 # ansible-core requirement
-pyyaml == 5.4.1 # needed for collection_detail.py
-voluptuous == 0.12.1
-
-# dependencies
-MarkupSafe == 2.0.1
+# edit "sanity.validate-modules.in" and generate with: hacking/update-sanity-requirements.py --test validate-modules
+Jinja2==3.0.3
+MarkupSafe==2.0.1
+PyYAML==6.0
+voluptuous==0.12.2
diff --git a/test/lib/ansible_test/_data/requirements/sanity.yamllint.in b/test/lib/ansible_test/_data/requirements/sanity.yamllint.in
new file mode 100644
index 0000000000..b2c729ca4d
--- /dev/null
+++ b/test/lib/ansible_test/_data/requirements/sanity.yamllint.in
@@ -0,0 +1 @@
+yamllint
diff --git a/test/lib/ansible_test/_data/requirements/sanity.yamllint.txt b/test/lib/ansible_test/_data/requirements/sanity.yamllint.txt
index 6738486394..7880699155 100644
--- a/test/lib/ansible_test/_data/requirements/sanity.yamllint.txt
+++ b/test/lib/ansible_test/_data/requirements/sanity.yamllint.txt
@@ -1,5 +1,4 @@
-yamllint == 1.26.0
-
-# dependencies
-pathspec == 0.9.0
-pyyaml == 5.4.1
+# edit "sanity.yamllint.in" and generate with: hacking/update-sanity-requirements.py --test yamllint
+pathspec==0.9.0
+PyYAML==6.0
+yamllint==1.26.3
diff --git a/test/lib/ansible_test/_internal/commands/sanity/__init__.py b/test/lib/ansible_test/_internal/commands/sanity/__init__.py
index 542e078ad1..b380509e6b 100644
--- a/test/lib/ansible_test/_internal/commands/sanity/__init__.py
+++ b/test/lib/ansible_test/_internal/commands/sanity/__init__.py
@@ -242,7 +242,7 @@ def command_sanity(args): # type: (SanityConfig) -> None
elif isinstance(test, SanitySingleVersion):
# single version sanity tests use the controller python
test_profile = host_state.controller_profile
- virtualenv_python = create_sanity_virtualenv(args, test_profile.python, test.name, context=test.name)
+ virtualenv_python = create_sanity_virtualenv(args, test_profile.python, test.name)
if virtualenv_python:
virtualenv_yaml = check_sanity_virtualenv_yaml(virtualenv_python)
@@ -1077,10 +1077,8 @@ def create_sanity_virtualenv(
args, # type: SanityConfig
python, # type: PythonConfig
name, # type: str
- ansible=False, # type: bool
coverage=False, # type: bool
minimize=False, # type: bool
- context=None, # type: t.Optional[str]
): # type: (...) -> t.Optional[VirtualPythonConfig]
"""Return an existing sanity virtual environment matching the requested parameters or create a new one."""
commands = collect_requirements( # create_sanity_virtualenv()
@@ -1088,13 +1086,11 @@ def create_sanity_virtualenv(
controller=True,
virtualenv=False,
command=None,
- # used by import tests
- ansible=ansible,
- cryptography=ansible,
+ ansible=False,
+ cryptography=False,
coverage=coverage,
minimize=minimize,
- # used by non-import tests
- sanity=context,
+ sanity=name,
)
if commands:
diff --git a/test/lib/ansible_test/_internal/commands/sanity/import.py b/test/lib/ansible_test/_internal/commands/sanity/import.py
index 19a67b4b29..4ab638ab44 100644
--- a/test/lib/ansible_test/_internal/commands/sanity/import.py
+++ b/test/lib/ansible_test/_internal/commands/sanity/import.py
@@ -87,8 +87,17 @@ class ImportTest(SanityMultipleVersion):
"""Sanity test for proper import exception handling."""
def filter_targets(self, targets): # type: (t.List[TestTarget]) -> t.List[TestTarget]
"""Return the given list of test targets, filtered to include only those relevant for the test."""
+ if data_context().content.is_ansible:
+ # all of ansible-core must pass the import test, not just plugins/modules
+ # modules/module_utils will be tested using the module context
+ # everything else will be tested using the plugin context
+ paths = ['lib/ansible']
+ else:
+ # only plugins/modules must pass the import test for collections
+ paths = list(data_context().content.plugin_paths.values())
+
return [target for target in targets if os.path.splitext(target.path)[1] == '.py' and
- any(is_subdir(target.path, path) for path in data_context().content.plugin_paths.values())]
+ any(is_subdir(target.path, path) for path in paths)]
@property
def needs_pypi(self): # type: () -> bool
@@ -112,9 +121,9 @@ class ImportTest(SanityMultipleVersion):
messages = []
- for import_type, test, controller in (
- ('module', _get_module_test(True), False),
- ('plugin', _get_module_test(False), True),
+ for import_type, test in (
+ ('module', _get_module_test(True)),
+ ('plugin', _get_module_test(False)),
):
if import_type == 'plugin' and python.version in REMOTE_ONLY_PYTHON_VERSIONS:
continue
@@ -124,7 +133,7 @@ class ImportTest(SanityMultipleVersion):
if not data and not args.prime_venvs:
continue
- virtualenv_python = create_sanity_virtualenv(args, python, f'{self.name}.{import_type}', ansible=controller, coverage=args.coverage, minimize=True)
+ virtualenv_python = create_sanity_virtualenv(args, python, f'{self.name}.{import_type}', coverage=args.coverage, minimize=True)
if not virtualenv_python:
display.warning(f'Skipping sanity test "{self.name}" on Python {python.version} due to missing virtual environment support.')
@@ -143,7 +152,7 @@ class ImportTest(SanityMultipleVersion):
)
if data_context().content.collection:
- external_python = create_sanity_virtualenv(args, args.controller_python, self.name, context=self.name)
+ external_python = create_sanity_virtualenv(args, args.controller_python, self.name)
env.update(
SANITY_COLLECTION_FULL_NAME=data_context().content.collection.full_name,
diff --git a/test/sanity/code-smell/botmeta.requirements.in b/test/sanity/code-smell/botmeta.requirements.in
new file mode 100644
index 0000000000..edd96991dd
--- /dev/null
+++ b/test/sanity/code-smell/botmeta.requirements.in
@@ -0,0 +1,2 @@
+pyyaml
+voluptuous
diff --git a/test/sanity/code-smell/botmeta.requirements.txt b/test/sanity/code-smell/botmeta.requirements.txt
index 1281a04528..69f4b4bd0d 100644
--- a/test/sanity/code-smell/botmeta.requirements.txt
+++ b/test/sanity/code-smell/botmeta.requirements.txt
@@ -1,2 +1,3 @@
-pyyaml == 5.4.1
-voluptuous == 0.12.1
+# edit "botmeta.requirements.in" and generate with: hacking/update-sanity-requirements.py --test botmeta
+PyYAML==6.0
+voluptuous==0.12.2
diff --git a/test/sanity/code-smell/deprecated-config.requirements.in b/test/sanity/code-smell/deprecated-config.requirements.in
new file mode 100644
index 0000000000..859c4ee7e6
--- /dev/null
+++ b/test/sanity/code-smell/deprecated-config.requirements.in
@@ -0,0 +1,2 @@
+jinja2 # ansible-core requirement
+pyyaml
diff --git a/test/sanity/code-smell/deprecated-config.requirements.txt b/test/sanity/code-smell/deprecated-config.requirements.txt
index a3a33e6c20..ca5e9115af 100644
--- a/test/sanity/code-smell/deprecated-config.requirements.txt
+++ b/test/sanity/code-smell/deprecated-config.requirements.txt
@@ -1,5 +1,4 @@
-jinja2 == 3.0.1 # ansible-core requirement
-pyyaml == 5.4.1
-
-# dependencies
-MarkupSafe == 2.0.1
+# edit "deprecated-config.requirements.in" and generate with: hacking/update-sanity-requirements.py --test deprecated-config
+Jinja2==3.0.3
+MarkupSafe==2.0.1
+PyYAML==6.0
diff --git a/test/sanity/code-smell/docs-build.requirements.in b/test/sanity/code-smell/docs-build.requirements.in
new file mode 100644
index 0000000000..87210630cc
--- /dev/null
+++ b/test/sanity/code-smell/docs-build.requirements.in
@@ -0,0 +1,8 @@
+jinja2
+pyyaml
+resolvelib < 0.6.0
+sphinx == 4.2.0
+sphinx-notfound-page
+sphinx-ansible-theme
+straight.plugin
+antsibull
diff --git a/test/sanity/code-smell/docs-build.requirements.txt b/test/sanity/code-smell/docs-build.requirements.txt
index 36fc363a0e..1462ae9aa5 100644
--- a/test/sanity/code-smell/docs-build.requirements.txt
+++ b/test/sanity/code-smell/docs-build.requirements.txt
@@ -1,50 +1,50 @@
-jinja2 == 3.0.1
-pyyaml == 5.4.1
-resolvelib == 0.5.4
-sphinx == 2.1.2
-sphinx-notfound-page == 0.7.1
-sphinx-ansible-theme == 0.8.0
-straight.plugin == 1.5.0
-antsibull == 0.26.0
-
-# dependencies
-MarkupSafe == 2.0.1
-aiofiles == 0.7.0
-aiohttp == 3.7.4.post0
-alabaster == 0.7.12
-ansible-pygments == 0.1.0
-antsibull-changelog == 0.9.0
-async-timeout == 3.0.1
-asyncio-pool == 0.5.2
-attrs == 21.2.0
-babel == 2.9.1
-certifi == 2021.5.30
-chardet == 4.0.0
-charset-normalizer == 2.0.5
-docutils == 0.17.1
-idna == 2.5
-imagesize == 1.2.0
-multidict == 5.1.0
-packaging == 21.0
-perky == 0.5.5
-pydantic == 1.8.2
-pygments == 2.10.0
-pyparsing == 2.4.7
-pytz == 2021.1
-requests == 2.26.0
-rstcheck == 3.3.1
-semantic-version == 2.8.5
-sh == 1.14.2
-six == 1.16.0
-snowballstemmer == 2.1.0
-sphinx-rtd-theme == 1.0.0
-sphinxcontrib-applehelp == 1.0.2
-sphinxcontrib-devhelp == 1.0.2
-sphinxcontrib-htmlhelp == 2.0.0
-sphinxcontrib-jsmath == 1.0.1
-sphinxcontrib-qthelp == 1.0.3
-sphinxcontrib-serializinghtml == 1.1.5
-twiggy == 0.5.1
-typing-extensions == 3.10.0.2
-urllib3 == 1.26.6
-yarl == 1.6.3
+# edit "docs-build.requirements.in" and generate with: hacking/update-sanity-requirements.py --test docs-build
+aiofiles==0.7.0
+aiohttp==3.8.0
+aiosignal==1.2.0
+alabaster==0.7.12
+ansible-pygments==0.1.0
+antsibull==0.39.2
+antsibull-changelog==0.12.0
+async-timeout==4.0.1
+asyncio-pool==0.5.2
+attrs==21.2.0
+Babel==2.9.1
+certifi==2021.10.8
+charset-normalizer==2.0.7
+docutils==0.17.1
+frozenlist==1.2.0
+idna==3.3
+imagesize==1.3.0
+Jinja2==3.0.3
+MarkupSafe==2.0.1
+multidict==5.2.0
+packaging==21.2
+perky==0.5.5
+pydantic==1.8.2
+Pygments==2.10.0
+pyparsing==2.4.7
+pytz==2021.3
+PyYAML==6.0
+requests==2.26.0
+resolvelib==0.5.4
+rstcheck==3.3.1
+semantic-version==2.8.5
+sh==1.14.2
+six==1.16.0
+snowballstemmer==2.1.0
+Sphinx==4.2.0
+sphinx-ansible-theme==0.8.0
+sphinx-notfound-page==0.8
+sphinx-rtd-theme==1.0.0
+sphinxcontrib-applehelp==1.0.2
+sphinxcontrib-devhelp==1.0.2
+sphinxcontrib-htmlhelp==2.0.0
+sphinxcontrib-jsmath==1.0.1
+sphinxcontrib-qthelp==1.0.3
+sphinxcontrib-serializinghtml==1.1.5
+straight.plugin==1.5.0
+Twiggy==0.5.1
+typing-extensions==3.10.0.2
+urllib3==1.26.7
+yarl==1.7.2
diff --git a/test/sanity/code-smell/package-data.requirements.in b/test/sanity/code-smell/package-data.requirements.in
new file mode 100644
index 0000000000..68c2248e58
--- /dev/null
+++ b/test/sanity/code-smell/package-data.requirements.in
@@ -0,0 +1,7 @@
+docutils < 0.18 # match version required by sphinx in the docs-build sanity test
+jinja2
+pyyaml # ansible-core requirement
+resolvelib < 0.6.0
+rstcheck
+straight.plugin
+antsibull-changelog
diff --git a/test/sanity/code-smell/package-data.requirements.txt b/test/sanity/code-smell/package-data.requirements.txt
index 8055b3c5c7..8b08b9a34e 100644
--- a/test/sanity/code-smell/package-data.requirements.txt
+++ b/test/sanity/code-smell/package-data.requirements.txt
@@ -1,13 +1,12 @@
-docutils == 0.17.1
-jinja2 == 3.0.1
-packaging == 21.0
-pyyaml == 5.4.1 # ansible-core requirement
-resolvelib == 0.5.4 # ansible-core requirement
-rstcheck == 3.3.1
-straight.plugin == 1.5.0
-antsibull-changelog == 0.9.0
-
-# dependencies
-MarkupSafe == 2.0.1
-pyparsing == 2.4.7
-semantic-version == 2.8.5
+# edit "package-data.requirements.in" and generate with: hacking/update-sanity-requirements.py --test package-data
+antsibull-changelog==0.12.0
+docutils==0.17.1
+Jinja2==3.0.3
+MarkupSafe==2.0.1
+packaging==21.2
+pyparsing==2.4.7
+PyYAML==6.0
+resolvelib==0.5.4
+rstcheck==3.3.1
+semantic-version==2.8.5
+straight.plugin==1.5.0
diff --git a/test/sanity/code-smell/release-names.requirements.in b/test/sanity/code-smell/release-names.requirements.in
new file mode 100644
index 0000000000..c3726e8bfe
--- /dev/null
+++ b/test/sanity/code-smell/release-names.requirements.in
@@ -0,0 +1 @@
+pyyaml
diff --git a/test/sanity/code-smell/release-names.requirements.txt b/test/sanity/code-smell/release-names.requirements.txt
index cc530e42c2..41ee6fa8d7 100644
--- a/test/sanity/code-smell/release-names.requirements.txt
+++ b/test/sanity/code-smell/release-names.requirements.txt
@@ -1 +1,2 @@
-pyyaml == 5.4.1
+# edit "release-names.requirements.in" and generate with: hacking/update-sanity-requirements.py --test release-names
+PyYAML==6.0
diff --git a/test/sanity/code-smell/rstcheck.requirements.in b/test/sanity/code-smell/rstcheck.requirements.in
new file mode 100644
index 0000000000..f997391281
--- /dev/null
+++ b/test/sanity/code-smell/rstcheck.requirements.in
@@ -0,0 +1,3 @@
+sphinx == 4.2.0 # required for full rstcheck functionality, installed first to get the correct docutils version
+rstcheck
+jinja2 # ansible-core requirement
diff --git a/test/sanity/code-smell/rstcheck.requirements.txt b/test/sanity/code-smell/rstcheck.requirements.txt
index 071bc5a1f1..f89165398a 100644
--- a/test/sanity/code-smell/rstcheck.requirements.txt
+++ b/test/sanity/code-smell/rstcheck.requirements.txt
@@ -1,27 +1,25 @@
-rstcheck == 3.3.1
-sphinx == 2.1.2 # required for full functionality
-
-# dependencies
-Jinja2 == 3.0.1
-MarkupSafe == 2.0.1
-Pygments == 2.10.0
-alabaster == 0.7.12
-babel == 2.9.1
-certifi == 2021.5.30
-charset-normalizer == 2.0.5
-docutils == 0.17.1
-idna == 2.5
-imagesize == 1.2.0
-packaging == 21.0
-pyparsing == 2.4.7
-pytz == 2021.1
-requests == 2.26.0
-rstcheck == 3.3.1
-snowballstemmer == 2.1.0
-sphinxcontrib-applehelp == 1.0.2
-sphinxcontrib-devhelp == 1.0.2
-sphinxcontrib-htmlhelp == 2.0.0
-sphinxcontrib-jsmath == 1.0.1
-sphinxcontrib-qthelp == 1.0.3
-sphinxcontrib-serializinghtml == 1.1.5
-urllib3 == 1.26.6
+# edit "rstcheck.requirements.in" and generate with: hacking/update-sanity-requirements.py --test rstcheck
+alabaster==0.7.12
+Babel==2.9.1
+certifi==2021.10.8
+charset-normalizer==2.0.7
+docutils==0.17.1
+idna==3.3
+imagesize==1.3.0
+Jinja2==3.0.3
+MarkupSafe==2.0.1
+packaging==21.2
+Pygments==2.10.0
+pyparsing==2.4.7
+pytz==2021.3
+requests==2.26.0
+rstcheck==3.3.1
+snowballstemmer==2.1.0
+Sphinx==4.2.0
+sphinxcontrib-applehelp==1.0.2
+sphinxcontrib-devhelp==1.0.2
+sphinxcontrib-htmlhelp==2.0.0
+sphinxcontrib-jsmath==1.0.1
+sphinxcontrib-qthelp==1.0.3
+sphinxcontrib-serializinghtml==1.1.5
+urllib3==1.26.7
diff --git a/test/sanity/code-smell/test-constraints.py b/test/sanity/code-smell/test-constraints.py
index 8383235e15..fd6f17d578 100644
--- a/test/sanity/code-smell/test-constraints.py
+++ b/test/sanity/code-smell/test-constraints.py
@@ -1,6 +1,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
+import os
import re
import sys
@@ -21,6 +22,11 @@ def main():
non_sanity_requirements = set()
for path, requirements in requirements.items():
+ filename = os.path.basename(path)
+
+ is_sanity = filename.startswith('sanity.') or filename.endswith('.requirements.txt')
+ is_constraints = path == constraints_path
+
for lineno, line, requirement in requirements:
if not requirement:
print('%s:%d:%d: cannot parse requirement: %s' % (path, lineno, 1, line))
@@ -28,14 +34,10 @@ def main():
name = requirement.group('name').lower()
raw_constraints = requirement.group('constraints')
- raw_markers = requirement.group('markers')
constraints = raw_constraints.strip()
- markers = raw_markers.strip()
comment = requirement.group('comment')
- is_sanity = path.startswith('test/lib/ansible_test/_data/requirements/sanity.') or path.startswith('test/sanity/code-smell/')
is_pinned = re.search('^ *== *[0-9.]+(\\.post[0-9]+)?$', constraints)
- is_constraints = path == constraints_path
if is_sanity:
sanity = frozen_sanity.setdefault(name, [])
@@ -43,20 +45,19 @@ def main():
elif not is_constraints:
non_sanity_requirements.add(name)
+ if is_sanity:
+ if not is_pinned:
+ # sanity test requirements must be pinned
+ print('%s:%d:%d: sanity test requirement (%s%s) must be frozen (use `==`)' % (path, lineno, 1, name, raw_constraints))
+
+ continue
+
if constraints and not is_constraints:
allow_constraints = 'sanity_ok' in comment
- if is_sanity and is_pinned and not markers:
- allow_constraints = True # sanity tests can use frozen requirements without markers
-
if not allow_constraints:
- if is_sanity:
- # sanity test requirements which need constraints should be frozen to maintain consistent test results
- # use of anything other than frozen constraints will make evaluation of conflicts extremely difficult
- print('%s:%d:%d: sanity test constraint (%s%s) must be frozen (use `==`)' % (path, lineno, 1, name, raw_constraints))
- else:
- # keeping constraints for tests other than sanity tests in one file helps avoid conflicts
- print('%s:%d:%d: put the constraint (%s%s) in `%s`' % (path, lineno, 1, name, raw_constraints, constraints_path))
+ # keeping constraints for tests other than sanity tests in one file helps avoid conflicts
+ print('%s:%d:%d: put the constraint (%s%s) in `%s`' % (path, lineno, 1, name, raw_constraints, constraints_path))
for name, requirements in frozen_sanity.items():
if len(set(req[3].group('constraints').strip() for req in requirements)) != 1:
diff --git a/test/sanity/code-smell/update-bundled.requirements.in b/test/sanity/code-smell/update-bundled.requirements.in
new file mode 100644
index 0000000000..748809f75c
--- /dev/null
+++ b/test/sanity/code-smell/update-bundled.requirements.in
@@ -0,0 +1 @@
+packaging
diff --git a/test/sanity/code-smell/update-bundled.requirements.txt b/test/sanity/code-smell/update-bundled.requirements.txt
index 101e3fdb55..93330e3483 100644
--- a/test/sanity/code-smell/update-bundled.requirements.txt
+++ b/test/sanity/code-smell/update-bundled.requirements.txt
@@ -1,4 +1,3 @@
-packaging == 21.0
-
-# dependencies
-pyparsing == 2.4.7
+# edit "update-bundled.requirements.in" and generate with: hacking/update-sanity-requirements.py --test update-bundled
+packaging==21.2
+pyparsing==2.4.7
diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt
index d056a698ce..d692cc2c70 100644
--- a/test/sanity/ignore.txt
+++ b/test/sanity/ignore.txt
@@ -4,6 +4,39 @@ docs/docsite/rst/locales/ja/LC_MESSAGES/dev_guide.po no-smart-quotes # Translat
examples/scripts/ConfigureRemotingForAnsible.ps1 pslint:PSCustomUseLiteralPath
examples/scripts/upgrade_to_ps3.ps1 pslint:PSCustomUseLiteralPath
examples/scripts/upgrade_to_ps3.ps1 pslint:PSUseApprovedVerbs
+lib/ansible/cli/galaxy.py import-3.8 # unguarded indirect resolvelib import
+lib/ansible/galaxy/collection/__init__.py import-3.8 # unguarded resolvelib import
+lib/ansible/galaxy/collection/concrete_artifact_manager.py import-3.8 # unguarded resolvelib import
+lib/ansible/galaxy/collection/galaxy_api_proxy.py import-3.8 # unguarded resolvelib imports
+lib/ansible/galaxy/dependency_resolution/__init__.py import-3.8 # circular imports
+lib/ansible/galaxy/dependency_resolution/dataclasses.py import-3.8 # circular imports
+lib/ansible/galaxy/dependency_resolution/errors.py import-3.8 # circular imports
+lib/ansible/galaxy/dependency_resolution/providers.py import-3.8 # circular imports
+lib/ansible/galaxy/dependency_resolution/reporters.py import-3.8 # circular imports
+lib/ansible/galaxy/dependency_resolution/resolvers.py import-3.8 # circular imports
+lib/ansible/galaxy/dependency_resolution/versioning.py import-3.8 # circular imports
+lib/ansible/cli/galaxy.py import-3.9 # unguarded indirect resolvelib import
+lib/ansible/galaxy/collection/__init__.py import-3.9 # unguarded resolvelib import
+lib/ansible/galaxy/collection/concrete_artifact_manager.py import-3.9 # unguarded resolvelib import
+lib/ansible/galaxy/collection/galaxy_api_proxy.py import-3.9 # unguarded resolvelib imports
+lib/ansible/galaxy/dependency_resolution/__init__.py import-3.9 # circular imports
+lib/ansible/galaxy/dependency_resolution/dataclasses.py import-3.9 # circular imports
+lib/ansible/galaxy/dependency_resolution/errors.py import-3.9 # circular imports
+lib/ansible/galaxy/dependency_resolution/providers.py import-3.9 # circular imports
+lib/ansible/galaxy/dependency_resolution/reporters.py import-3.9 # circular imports
+lib/ansible/galaxy/dependency_resolution/resolvers.py import-3.9 # circular imports
+lib/ansible/galaxy/dependency_resolution/versioning.py import-3.9 # circular imports
+lib/ansible/cli/galaxy.py import-3.10 # unguarded indirect resolvelib import
+lib/ansible/galaxy/collection/__init__.py import-3.10 # unguarded resolvelib import
+lib/ansible/galaxy/collection/concrete_artifact_manager.py import-3.10 # unguarded resolvelib import
+lib/ansible/galaxy/collection/galaxy_api_proxy.py import-3.10 # unguarded resolvelib imports
+lib/ansible/galaxy/dependency_resolution/__init__.py import-3.10 # circular imports
+lib/ansible/galaxy/dependency_resolution/dataclasses.py import-3.10 # circular imports
+lib/ansible/galaxy/dependency_resolution/errors.py import-3.10 # circular imports
+lib/ansible/galaxy/dependency_resolution/providers.py import-3.10 # circular imports
+lib/ansible/galaxy/dependency_resolution/reporters.py import-3.10 # circular imports
+lib/ansible/galaxy/dependency_resolution/resolvers.py import-3.10 # circular imports
+lib/ansible/galaxy/dependency_resolution/versioning.py import-3.10 # circular imports
lib/ansible/cli/scripts/ansible_connection_cli_stub.py shebang
lib/ansible/config/base.yml no-unwanted-files
lib/ansible/executor/playbook_executor.py pylint:disallowed-name