diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 20:03:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 20:03:01 +0000 |
commit | a453ac31f3428614cceb99027f8efbdb9258a40b (patch) | |
tree | f61f87408f32a8511cbd91799f9cececb53e0374 /test/sanity | |
parent | Initial commit. (diff) | |
download | ansible-a453ac31f3428614cceb99027f8efbdb9258a40b.tar.xz ansible-a453ac31f3428614cceb99027f8efbdb9258a40b.zip |
Adding upstream version 2.10.7+merged+base+2.10.8+dfsg.upstream/2.10.7+merged+base+2.10.8+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/sanity')
27 files changed, 1542 insertions, 0 deletions
diff --git a/test/sanity/code-smell/configure-remoting-ps1.json b/test/sanity/code-smell/configure-remoting-ps1.json new file mode 100644 index 00000000..593b765d --- /dev/null +++ b/test/sanity/code-smell/configure-remoting-ps1.json @@ -0,0 +1,4 @@ +{ + "no_targets": true, + "output": "path-message" +} diff --git a/test/sanity/code-smell/configure-remoting-ps1.py b/test/sanity/code-smell/configure-remoting-ps1.py new file mode 100755 index 00000000..51dff20c --- /dev/null +++ b/test/sanity/code-smell/configure-remoting-ps1.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os + + +def main(): + # required by external automated processes and should not be moved, renamed or converted to a symbolic link + original = 'examples/scripts/ConfigureRemotingForAnsible.ps1' + # required to be packaged with ansible-test and must match the original file, but cannot be a symbolic link + # the packaged version is needed to run tests when ansible-test has been installed + # keeping the packaged version identical to the original makes sure tests cover both files + packaged = 'test/lib/ansible_test/_data/setup/ConfigureRemotingForAnsible.ps1' + + copy_valid = False + + if os.path.isfile(original) and os.path.isfile(packaged): + with open(original, 'rb') as original_file: + original_content = original_file.read() + + with open(packaged, 'rb') as packaged_file: + packaged_content = packaged_file.read() + + if original_content == packaged_content: + copy_valid = True + + if not copy_valid: + print('%s: must be an exact copy of "%s"' % (packaged, original)) + + for path in [original, packaged]: + directory = path + + while True: + directory = os.path.dirname(directory) + + if not directory: + break + + if not os.path.isdir(directory): + print('%s: must be a directory' % directory) + + if os.path.islink(directory): + print('%s: cannot be a symbolic link' % directory) + + if not os.path.isfile(path): + print('%s: must be a file' % path) + + if os.path.islink(path): + print('%s: cannot be a symbolic link' % path) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/deprecated-config.json b/test/sanity/code-smell/deprecated-config.json new file mode 100644 index 00000000..4a884860 --- /dev/null +++ b/test/sanity/code-smell/deprecated-config.json @@ -0,0 +1,10 @@ +{ + "all_targets": true, + "output": "path-message", + "extensions": [ + ".py" + ], + "prefixes": [ + "lib/ansible/" + ] +} diff --git a/test/sanity/code-smell/deprecated-config.py b/test/sanity/code-smell/deprecated-config.py new file mode 100755 index 00000000..08e93c36 --- /dev/null +++ b/test/sanity/code-smell/deprecated-config.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# (c) 2018, Matt Martz <matt@sivel.net> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import mmap +import os +import re +import sys + +from distutils.version import StrictVersion + +import yaml + +import ansible.config + +from ansible.plugins.loader import fragment_loader +from ansible.release import __version__ as ansible_version +from ansible.utils.plugin_docs import get_docstring + +DOC_RE = re.compile(b'^DOCUMENTATION', flags=re.M) +ANSIBLE_MAJOR = StrictVersion('.'.join(ansible_version.split('.')[:2])) + + +def find_deprecations(obj, path=None): + if not isinstance(obj, (list, dict)): + return + + try: + items = obj.items() + except AttributeError: + items = enumerate(obj) + + for key, value in items: + if path is None: + this_path = [] + else: + this_path = path[:] + + this_path.append(key) + + if key != 'deprecated': + for result in find_deprecations(value, path=this_path): + yield result + else: + try: + version = value['version'] + this_path.append('version') + except KeyError: + version = value['removed_in'] + this_path.append('removed_in') + if StrictVersion(version) <= ANSIBLE_MAJOR: + yield (this_path, version) + + +def main(): + plugins = [] + for path in sys.argv[1:] or sys.stdin.read().splitlines(): + with open(path, 'rb') as f: + try: + mm_file = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + except ValueError: + continue + if DOC_RE.search(mm_file): + plugins.append(path) + mm_file.close() + + for plugin in plugins: + data = {} + data['doc'], data['examples'], data['return'], data['metadata'] = get_docstring(plugin, fragment_loader) + for result in find_deprecations(data['doc']): + print( + '%s: %s is scheduled for removal in %s' % (plugin, '.'.join(str(i) for i in result[0][:-2]), result[1]) + ) + + base = os.path.join(os.path.dirname(ansible.config.__file__), 'base.yml') + with open(base) as f: + data = yaml.safe_load(f) + + for result in find_deprecations(data): + print('%s: %s is scheduled for removal in %s' % (base, '.'.join(str(i) for i in result[0][:-2]), result[1])) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/deprecated-config.requirements.txt b/test/sanity/code-smell/deprecated-config.requirements.txt new file mode 100644 index 00000000..cfefdeec --- /dev/null +++ b/test/sanity/code-smell/deprecated-config.requirements.txt @@ -0,0 +1,2 @@ +jinja2 # ansible-base requirement +pyyaml diff --git a/test/sanity/code-smell/docs-build.json b/test/sanity/code-smell/docs-build.json new file mode 100644 index 00000000..0218bfc5 --- /dev/null +++ b/test/sanity/code-smell/docs-build.json @@ -0,0 +1,6 @@ +{ + "intercept": true, + "disabled": true, + "no_targets": true, + "output": "path-line-column-message" +} diff --git a/test/sanity/code-smell/docs-build.py b/test/sanity/code-smell/docs-build.py new file mode 100755 index 00000000..80eca15f --- /dev/null +++ b/test/sanity/code-smell/docs-build.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import re +import shutil +import subprocess +import sys +import tempfile + + +def main(): + base_dir = os.getcwd() + os.path.sep + docs_dir = os.path.abspath('docs/docsite') + + # TODO: Remove this temporary hack to constrain 'cryptography' when we have + # a better story for dealing with it. + tmpfd, tmp = tempfile.mkstemp() + requirements_txt = os.path.join(base_dir, 'requirements.txt') + shutil.copy2(requirements_txt, tmp) + lines = [] + with open(requirements_txt, 'r') as f: + for line in f.readlines(): + if line.strip() == 'cryptography': + line = 'cryptography < 3.4\n' + lines.append(line) + + with open(requirements_txt, 'w') as f: + f.writelines(lines) + + try: + cmd = ['make', 'core_singlehtmldocs'] + sphinx = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=docs_dir) + stdout, stderr = sphinx.communicate() + finally: + shutil.move(tmp, requirements_txt) + + stdout = stdout.decode('utf-8') + stderr = stderr.decode('utf-8') + + if sphinx.returncode != 0: + sys.stderr.write("Command '%s' failed with status code: %d\n" % (' '.join(cmd), sphinx.returncode)) + + if stdout.strip(): + stdout = simplify_stdout(stdout) + + sys.stderr.write("--> Standard Output\n") + sys.stderr.write("%s\n" % stdout.strip()) + + if stderr.strip(): + sys.stderr.write("--> Standard Error\n") + sys.stderr.write("%s\n" % stderr.strip()) + + sys.exit(1) + + with open('docs/docsite/rst_warnings', 'r') as warnings_fd: + output = warnings_fd.read().strip() + lines = output.splitlines() + + known_warnings = { + 'block-quote-missing-blank-line': r'^Block quote ends without a blank line; unexpected unindent.$', + 'literal-block-lex-error': r'^Could not lex literal_block as "[^"]*". Highlighting skipped.$', + 'duplicate-label': r'^duplicate label ', + 'undefined-label': r'undefined label: ', + 'unknown-document': r'unknown document: ', + 'toc-tree-missing-document': r'toctree contains reference to nonexisting document ', + 'reference-target-not-found': r'[^ ]* reference target not found: ', + 'not-in-toc-tree': r"document isn't included in any toctree$", + 'unexpected-indentation': r'^Unexpected indentation.$', + 'definition-list-missing-blank-line': r'^Definition list ends without a blank line; unexpected unindent.$', + 'explicit-markup-missing-blank-line': r'Explicit markup ends without a blank line; unexpected unindent.$', + 'toc-tree-glob-pattern-no-match': r"^toctree glob pattern '[^']*' didn't match any documents$", + 'unknown-interpreted-text-role': '^Unknown interpreted text role "[^"]*".$', + } + + for line in lines: + match = re.search('^(?P<path>[^:]+):((?P<line>[0-9]+):)?((?P<column>[0-9]+):)? (?P<level>WARNING|ERROR): (?P<message>.*)$', line) + + if not match: + path = 'docs/docsite/rst/index.rst' + lineno = 0 + column = 0 + code = 'unknown' + message = line + + # surface unknown lines while filtering out known lines to avoid excessive output + print('%s:%d:%d: %s: %s' % (path, lineno, column, code, message)) + continue + + path = match.group('path') + lineno = int(match.group('line') or 0) + column = int(match.group('column') or 0) + level = match.group('level').lower() + message = match.group('message') + + path = os.path.abspath(path) + + if path.startswith(base_dir): + path = path[len(base_dir):] + + if path.startswith('rst/'): + path = 'docs/docsite/' + path # fix up paths reported relative to `docs/docsite/` + + if level == 'warning': + code = 'warning' + + for label, pattern in known_warnings.items(): + if re.search(pattern, message): + code = label + break + else: + code = 'error' + + print('%s:%d:%d: %s: %s' % (path, lineno, column, code, message)) + + +def simplify_stdout(value): + """Simplify output by omitting earlier 'rendering: ...' messages.""" + lines = value.strip().splitlines() + + rendering = [] + keep = [] + + def truncate_rendering(): + """Keep last rendering line (if any) with a message about omitted lines as needed.""" + if not rendering: + return + + notice = rendering[-1] + + if len(rendering) > 1: + notice += ' (%d previous rendering line(s) omitted)' % (len(rendering) - 1) + + keep.append(notice) + # Could change to rendering.clear() if we do not support python2 + rendering[:] = [] + + for line in lines: + if line.startswith('rendering: '): + rendering.append(line) + continue + + truncate_rendering() + keep.append(line) + + truncate_rendering() + + result = '\n'.join(keep) + + return result + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/docs-build.requirements.txt b/test/sanity/code-smell/docs-build.requirements.txt new file mode 100644 index 00000000..5e458795 --- /dev/null +++ b/test/sanity/code-smell/docs-build.requirements.txt @@ -0,0 +1,6 @@ +jinja2 +pyyaml +sphinx +sphinx-notfound-page +straight.plugin +antsibull diff --git a/test/sanity/code-smell/no-unwanted-files.json b/test/sanity/code-smell/no-unwanted-files.json new file mode 100644 index 00000000..7a89ebbe --- /dev/null +++ b/test/sanity/code-smell/no-unwanted-files.json @@ -0,0 +1,7 @@ +{ + "include_symlinks": true, + "prefixes": [ + "lib/" + ], + "output": "path-message" +} diff --git a/test/sanity/code-smell/no-unwanted-files.py b/test/sanity/code-smell/no-unwanted-files.py new file mode 100755 index 00000000..bff09152 --- /dev/null +++ b/test/sanity/code-smell/no-unwanted-files.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +"""Prevent unwanted files from being added to the source tree.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import sys + + +def main(): + """Main entry point.""" + paths = sys.argv[1:] or sys.stdin.read().splitlines() + + allowed_extensions = ( + '.cs', + '.ps1', + '.psm1', + '.py', + ) + + skip_paths = set([ + 'lib/ansible/config/ansible_builtin_runtime.yml', # not included in the sanity ignore file since it won't exist until after migration + ]) + + skip_directories = ( + 'lib/ansible/galaxy/data/', + ) + + for path in paths: + if path in skip_paths: + continue + + if any(path.startswith(skip_directory) for skip_directory in skip_directories): + continue + + if path.startswith('lib/') and not path.startswith('lib/ansible/'): + print('%s: all "lib" content must reside in the "lib/ansible" directory' % path) + continue + + ext = os.path.splitext(path)[1] + + if ext not in allowed_extensions: + print('%s: extension must be one of: %s' % (path, ', '.join(allowed_extensions))) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/obsolete-files.json b/test/sanity/code-smell/obsolete-files.json new file mode 100644 index 00000000..02d39204 --- /dev/null +++ b/test/sanity/code-smell/obsolete-files.json @@ -0,0 +1,17 @@ +{ + "include_symlinks": true, + "prefixes": [ + "test/runner/", + "test/sanity/ansible-doc/", + "test/sanity/compile/", + "test/sanity/import/", + "test/sanity/pep8/", + "test/sanity/pslint/", + "test/sanity/pylint/", + "test/sanity/rstcheck/", + "test/sanity/shellcheck/", + "test/sanity/validate-modules/", + "test/sanity/yamllint/" + ], + "output": "path-message" +} diff --git a/test/sanity/code-smell/obsolete-files.py b/test/sanity/code-smell/obsolete-files.py new file mode 100755 index 00000000..e9ddc8a5 --- /dev/null +++ b/test/sanity/code-smell/obsolete-files.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +"""Prevent files from being added to directories that are now obsolete.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import sys + + +def main(): + """Main entry point.""" + paths = sys.argv[1:] or sys.stdin.read().splitlines() + + for path in paths: + print('%s: directory "%s/" is obsolete and should not contain any files' % (path, os.path.dirname(path))) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/package-data.json b/test/sanity/code-smell/package-data.json new file mode 100644 index 00000000..2b8a5326 --- /dev/null +++ b/test/sanity/code-smell/package-data.json @@ -0,0 +1,6 @@ +{ + "intercept": true, + "disabled": true, + "all_targets": true, + "output": "path-message" +} diff --git a/test/sanity/code-smell/package-data.py b/test/sanity/code-smell/package-data.py new file mode 100755 index 00000000..ca5f5ef5 --- /dev/null +++ b/test/sanity/code-smell/package-data.py @@ -0,0 +1,379 @@ +#!/usr/bin/env python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import contextlib +import fnmatch +import glob +import os +import re +import shutil +import subprocess +import sys +import tarfile +import tempfile + + +def assemble_files_to_ship(complete_file_list): + """ + This looks for all files which should be shipped in the sdist + """ + # All files which are in the repository except these: + ignore_patterns = ( + # Developer-only tools + '.azure-pipelines/*', + '.github/*', + '.github/*/*', + 'changelogs/fragments/*', + 'hacking/backport/*', + 'hacking/shippable/*', + 'hacking/tests/*', + 'hacking/ticket_stubs/*', + 'test/sanity/code-smell/botmeta.*', + 'test/utils/*', + 'test/utils/*/*', + 'test/utils/*/*/*', + '.git*', + ) + ignore_files = frozenset(( + # Developer-only tools + 'changelogs/config.yaml', + 'hacking/README.md', + 'hacking/ansible-profile', + 'hacking/cgroup_perf_recap_graph.py', + 'hacking/create_deprecated_issues.py', + 'hacking/deprecated_issue_template.md', + 'hacking/fix_test_syntax.py', + 'hacking/get_library.py', + 'hacking/metadata-tool.py', + 'hacking/report.py', + 'hacking/return_skeleton_generator.py', + 'hacking/test-module', + 'hacking/test-module.py', + 'test/support/README.md', + '.cherry_picker.toml', + '.mailmap', + # Generated as part of a build step + 'docs/docsite/rst/conf.py', + 'docs/docsite/rst/index.rst', + # Possibly should be included + 'examples/scripts/uptime.py', + 'examples/scripts/my_test.py', + 'examples/scripts/my_test_info.py', + 'examples/scripts/my_test_facts.py', + 'examples/DOCUMENTATION.yml', + 'examples/play.yml', + 'examples/hosts.yaml', + 'examples/hosts.yml', + 'examples/inventory_script_schema.json', + 'examples/plugin_filters.yml', + 'hacking/env-setup', + 'hacking/env-setup.fish', + 'MANIFEST', + )) + + # These files are generated and then intentionally added to the sdist + + # Manpages + manpages = ['docs/man/man1/ansible.1'] + for dirname, dummy, files in os.walk('bin'): + for filename in files: + path = os.path.join(dirname, filename) + if os.path.islink(path): + if os.readlink(path) == 'ansible': + manpages.append('docs/man/man1/%s.1' % filename) + + # Misc + misc_generated_files = [ + 'SYMLINK_CACHE.json', + 'PKG-INFO', + ] + + shipped_files = manpages + misc_generated_files + + for path in complete_file_list: + if path not in ignore_files: + for ignore in ignore_patterns: + if fnmatch.fnmatch(path, ignore): + break + else: + shipped_files.append(path) + + return shipped_files + + +def assemble_files_to_install(complete_file_list): + """ + This looks for all of the files which should show up in an installation of ansible + """ + ignore_patterns = tuple() + + pkg_data_files = [] + for path in complete_file_list: + + if path.startswith("lib/ansible"): + prefix = 'lib' + elif path.startswith("test/lib/ansible_test"): + prefix = 'test/lib' + else: + continue + + for ignore in ignore_patterns: + if fnmatch.fnmatch(path, ignore): + break + else: + pkg_data_files.append(os.path.relpath(path, prefix)) + + return pkg_data_files + + +@contextlib.contextmanager +def clean_repository(file_list): + """Copy the repository to clean it of artifacts""" + # Create a tempdir that will be the clean repo + with tempfile.TemporaryDirectory() as repo_root: + directories = set((repo_root + os.path.sep,)) + + for filename in file_list: + # Determine if we need to create the directory + directory = os.path.dirname(filename) + dest_dir = os.path.join(repo_root, directory) + if dest_dir not in directories: + os.makedirs(dest_dir) + + # Keep track of all the directories that now exist + path_components = directory.split(os.path.sep) + path = repo_root + for component in path_components: + path = os.path.join(path, component) + if path not in directories: + directories.add(path) + + # Copy the file + shutil.copy2(filename, dest_dir, follow_symlinks=False) + + yield repo_root + + +def create_sdist(tmp_dir): + """Create an sdist in the repository""" + create = subprocess.Popen( + ['make', 'snapshot', 'SDIST_DIR=%s' % tmp_dir], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + ) + + stderr = create.communicate()[1] + + if create.returncode != 0: + raise Exception('make snapshot failed:\n%s' % stderr) + + # Determine path to sdist + tmp_dir_files = os.listdir(tmp_dir) + + if not tmp_dir_files: + raise Exception('sdist was not created in the temp dir') + elif len(tmp_dir_files) > 1: + raise Exception('Unexpected extra files in the temp dir') + + return os.path.join(tmp_dir, tmp_dir_files[0]) + + +def extract_sdist(sdist_path, tmp_dir): + """Untar the sdist""" + # Untar the sdist from the tmp_dir + with tarfile.open(os.path.join(tmp_dir, sdist_path), 'r|*') as sdist: + sdist.extractall(path=tmp_dir) + + # Determine the sdist directory name + sdist_filename = os.path.basename(sdist_path) + tmp_dir_files = os.listdir(tmp_dir) + try: + tmp_dir_files.remove(sdist_filename) + except ValueError: + # Unexpected could not find original sdist in temp dir + raise + + if len(tmp_dir_files) > 1: + raise Exception('Unexpected extra files in the temp dir') + elif len(tmp_dir_files) < 1: + raise Exception('sdist extraction did not occur i nthe temp dir') + + return os.path.join(tmp_dir, tmp_dir_files[0]) + + +def install_sdist(tmp_dir, sdist_dir): + """Install the extracted sdist into the temporary directory""" + install = subprocess.Popen( + ['python', 'setup.py', 'install', '--root=%s' % tmp_dir], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + cwd=os.path.join(tmp_dir, sdist_dir), + ) + + stdout, stderr = install.communicate() + + if install.returncode != 0: + raise Exception('sdist install failed:\n%s' % stderr) + + # Determine the prefix for the installed files + match = re.search('^creating (%s/.*?/(?:site|dist)-packages)/ansible$' % + tmp_dir, stdout, flags=re.M) + return match.group(1) + + +def check_sdist_contains_expected(sdist_dir, to_ship_files): + """Check that the files we expect to ship are present in the sdist""" + results = [] + for filename in to_ship_files: + path = os.path.join(sdist_dir, filename) + if not os.path.exists(path): + results.append('%s: File was not added to sdist' % filename) + + # Also changelog + changelog_files = glob.glob(os.path.join(sdist_dir, 'changelogs/CHANGELOG-v2.[0-9]*.rst')) + if not changelog_files: + results.append('changelogs/CHANGELOG-v2.*.rst: Changelog file was not added to the sdist') + elif len(changelog_files) > 1: + results.append('changelogs/CHANGELOG-v2.*.rst: Too many changelog files: %s' + % changelog_files) + + return results + + +def check_sdist_files_are_wanted(sdist_dir, to_ship_files): + """Check that all files in the sdist are desired""" + results = [] + for dirname, dummy, files in os.walk(sdist_dir): + dirname = os.path.relpath(dirname, start=sdist_dir) + if dirname == '.': + dirname = '' + + for filename in files: + path = os.path.join(dirname, filename) + if path not in to_ship_files: + if fnmatch.fnmatch(path, 'changelogs/CHANGELOG-v2.[0-9]*.rst'): + # changelog files are expected + continue + + # FIXME: ansible-test doesn't pass the paths of symlinks to us so we aren't + # checking those + if not os.path.islink(os.path.join(sdist_dir, path)): + results.append('%s: File in sdist was not in the repository' % path) + + return results + + +def check_installed_contains_expected(install_dir, to_install_files): + """Check that all the files we expect to be installed are""" + results = [] + for filename in to_install_files: + path = os.path.join(install_dir, filename) + if not os.path.exists(path): + results.append('%s: File not installed' % os.path.join('lib', filename)) + + return results + + +EGG_RE = re.compile('ansible[^/]+\\.egg-info/(PKG-INFO|SOURCES.txt|' + 'dependency_links.txt|not-zip-safe|requires.txt|top_level.txt)$') + + +def check_installed_files_are_wanted(install_dir, to_install_files): + """Check that all installed files were desired""" + results = [] + + for dirname, dummy, files in os.walk(install_dir): + dirname = os.path.relpath(dirname, start=install_dir) + if dirname == '.': + dirname = '' + + for filename in files: + # If this is a byte code cache, look for the python file's name + directory = dirname + if filename.endswith('.pyc') or filename.endswith('.pyo'): + # Remove the trailing "o" or c" + filename = filename[:-1] + + if directory.endswith('%s__pycache__' % os.path.sep): + # Python3 byte code cache, look for the basename of + # __pycache__/__init__.cpython-36.py + segments = filename.rsplit('.', 2) + if len(segments) >= 3: + filename = '.'.join((segments[0], segments[2])) + directory = os.path.dirname(directory) + + path = os.path.join(directory, filename) + + # Test that the file was listed for installation + if path not in to_install_files: + # FIXME: ansible-test doesn't pass the paths of symlinks to us so we + # aren't checking those + if not os.path.islink(os.path.join(install_dir, path)): + if not EGG_RE.match(path): + results.append('%s: File was installed but was not supposed to be' % path) + + return results + + +def _find_symlinks(): + symlink_list = [] + for dirname, directories, filenames in os.walk('.'): + for filename in filenames: + path = os.path.join(dirname, filename) + # Strip off "./" from the front + path = path[2:] + if os.path.islink(path): + symlink_list.append(path) + + return symlink_list + + +def main(): + """All of the files in the repository""" + complete_file_list = [] + for path in sys.argv[1:] or sys.stdin.read().splitlines(): + complete_file_list.append(path) + + # ansible-test isn't currently passing symlinks to us so construct those ourselves for now + for filename in _find_symlinks(): + if filename not in complete_file_list: + # For some reason ansible-test is passing us lib/ansible/module_utils/ansible_release.py + # which is a symlink even though it doesn't pass any others + complete_file_list.append(filename) + + # We may run this after docs sanity tests so get a clean repository to run in + with clean_repository(complete_file_list) as clean_repo_dir: + os.chdir(clean_repo_dir) + + to_ship_files = assemble_files_to_ship(complete_file_list) + to_install_files = assemble_files_to_install(complete_file_list) + + results = [] + with tempfile.TemporaryDirectory() as tmp_dir: + sdist_path = create_sdist(tmp_dir) + sdist_dir = extract_sdist(sdist_path, tmp_dir) + + # Check that the files that are supposed to be in the sdist are there + results.extend(check_sdist_contains_expected(sdist_dir, to_ship_files)) + + # Check that the files that are in the sdist are in the repository + results.extend(check_sdist_files_are_wanted(sdist_dir, to_ship_files)) + + # install the sdist + install_dir = install_sdist(tmp_dir, sdist_dir) + + # Check that the files that are supposed to be installed are there + results.extend(check_installed_contains_expected(install_dir, to_install_files)) + + # Check that the files that are installed are supposed to be installed + results.extend(check_installed_files_are_wanted(install_dir, to_install_files)) + + for message in results: + print(message) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/package-data.requirements.txt b/test/sanity/code-smell/package-data.requirements.txt new file mode 100644 index 00000000..5d74c715 --- /dev/null +++ b/test/sanity/code-smell/package-data.requirements.txt @@ -0,0 +1,10 @@ +docutils +jinja2 +packaging +pyyaml # ansible-base requirement +rstcheck +setuptools > 39.2 +straight.plugin + +# changelog build requires python 3.6+ +antsibull-changelog ; python_version >= '3.6' diff --git a/test/sanity/code-smell/release-names.json b/test/sanity/code-smell/release-names.json new file mode 100644 index 00000000..593b765d --- /dev/null +++ b/test/sanity/code-smell/release-names.json @@ -0,0 +1,4 @@ +{ + "no_targets": true, + "output": "path-message" +} diff --git a/test/sanity/code-smell/release-names.py b/test/sanity/code-smell/release-names.py new file mode 100755 index 00000000..f8003320 --- /dev/null +++ b/test/sanity/code-smell/release-names.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# (c) 2019, Ansible Project +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +""" +Test that the release name is present in the list of used up release names +""" + + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from yaml import safe_load + +from ansible.release import __codename__ + + +def main(): + """Entrypoint to the script""" + + with open('.github/RELEASE_NAMES.yml') as f: + releases = safe_load(f.read()) + + # Why this format? The file's sole purpose is to be read by a human when they need to know + # which release names have already been used. So: + # 1) It's easier for a human to find the release names when there's one on each line + # 2) It helps keep other people from using the file and then asking for new features in it + for name in (r.split(maxsplit=1)[1] for r in releases): + if __codename__ == name: + break + else: + print('.github/RELEASE_NAMES.yml: Current codename was not present in the file') + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/release-names.requirements.txt b/test/sanity/code-smell/release-names.requirements.txt new file mode 100644 index 00000000..c3726e8b --- /dev/null +++ b/test/sanity/code-smell/release-names.requirements.txt @@ -0,0 +1 @@ +pyyaml diff --git a/test/sanity/code-smell/required-and-default-attributes.json b/test/sanity/code-smell/required-and-default-attributes.json new file mode 100644 index 00000000..dd9ac7b1 --- /dev/null +++ b/test/sanity/code-smell/required-and-default-attributes.json @@ -0,0 +1,9 @@ +{ + "prefixes": [ + "lib/ansible/" + ], + "extensions": [ + ".py" + ], + "output": "path-line-column-message" +} diff --git a/test/sanity/code-smell/required-and-default-attributes.py b/test/sanity/code-smell/required-and-default-attributes.py new file mode 100755 index 00000000..5ef410bd --- /dev/null +++ b/test/sanity/code-smell/required-and-default-attributes.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import re +import sys + + +def main(): + for path in sys.argv[1:] or sys.stdin.read().splitlines(): + with open(path, 'r') as path_fd: + for line, text in enumerate(path_fd.readlines()): + match = re.search(r'(FieldAttribute.*(default|required).*(default|required))', text) + + if match: + print('%s:%d:%d: use only one of `default` or `required` with `FieldAttribute`' % ( + path, line + 1, match.start(1) + 1)) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/skip.txt b/test/sanity/code-smell/skip.txt new file mode 100644 index 00000000..6fb327b3 --- /dev/null +++ b/test/sanity/code-smell/skip.txt @@ -0,0 +1,2 @@ +deprecated-config.py # disabled by default, to be enabled by the release manager after branching +update-bundled.py # disabled by default, to be enabled by the release manager after branching diff --git a/test/sanity/code-smell/test-constraints.json b/test/sanity/code-smell/test-constraints.json new file mode 100644 index 00000000..69b07bf3 --- /dev/null +++ b/test/sanity/code-smell/test-constraints.json @@ -0,0 +1,9 @@ +{ + "prefixes": [ + "test/lib/ansible_test/_data/requirements/" + ], + "extensions": [ + ".txt" + ], + "output": "path-line-column-message" +} diff --git a/test/sanity/code-smell/test-constraints.py b/test/sanity/code-smell/test-constraints.py new file mode 100755 index 00000000..e8b9c795 --- /dev/null +++ b/test/sanity/code-smell/test-constraints.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import re +import sys + + +def main(): + for path in sys.argv[1:] or sys.stdin.read().splitlines(): + with open(path, 'r') as path_fd: + for line, text in enumerate(path_fd.readlines()): + match = re.search(r'^[^;#]*?([<>=])(?!.*sanity_ok.*)', text) + + if match: + print('%s:%d:%d: put constraints in `test/lib/ansible_test/_data/requirements/constraints.txt`' % ( + path, line + 1, match.start(1) + 1)) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/update-bundled.json b/test/sanity/code-smell/update-bundled.json new file mode 100644 index 00000000..379bf4d7 --- /dev/null +++ b/test/sanity/code-smell/update-bundled.json @@ -0,0 +1,8 @@ +{ + "all_targets": true, + "ignore_self": true, + "extensions": [ + ".py" + ], + "output": "path-message" +} diff --git a/test/sanity/code-smell/update-bundled.py b/test/sanity/code-smell/update-bundled.py new file mode 100755 index 00000000..121e225f --- /dev/null +++ b/test/sanity/code-smell/update-bundled.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# (c) 2018, Ansible Project +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +""" +This test checks whether the libraries we're bundling are out of date and need to be synced with +a newer upstream release. +""" + + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import fnmatch +import json +import re +import sys +from distutils.version import LooseVersion + +import packaging.specifiers + +from ansible.module_utils.urls import open_url + + +BUNDLED_RE = re.compile(b'\\b_BUNDLED_METADATA\\b') + + +def get_bundled_libs(paths): + """ + Return the set of known bundled libraries + + :arg paths: The paths which the test has been instructed to check + :returns: The list of all files which we know to contain bundled libraries. If a bundled + library consists of multiple files, this should be the file which has metadata included. + """ + bundled_libs = set() + for filename in fnmatch.filter(paths, 'lib/ansible/compat/*/__init__.py'): + bundled_libs.add(filename) + + bundled_libs.add('lib/ansible/module_utils/distro/__init__.py') + bundled_libs.add('lib/ansible/module_utils/six/__init__.py') + bundled_libs.add('lib/ansible/module_utils/compat/ipaddress.py') + # backports.ssl_match_hostname should be moved to its own file in the future + bundled_libs.add('lib/ansible/module_utils/urls.py') + + return bundled_libs + + +def get_files_with_bundled_metadata(paths): + """ + Search for any files which have bundled metadata inside of them + + :arg paths: Iterable of filenames to search for metadata inside of + :returns: A set of pathnames which contained metadata + """ + + with_metadata = set() + for path in paths: + with open(path, 'rb') as f: + body = f.read() + + if BUNDLED_RE.search(body): + with_metadata.add(path) + + return with_metadata + + +def get_bundled_metadata(filename): + """ + Retrieve the metadata about a bundled library from a python file + + :arg filename: The filename to look inside for the metadata + :raises ValueError: If we're unable to extract metadata from the file + :returns: The metadata from the python file + """ + with open(filename, 'r') as module: + for line in module: + if line.strip().startswith('_BUNDLED_METADATA'): + data = line[line.index('{'):].strip() + break + else: + raise ValueError('Unable to check bundled library for update. Please add' + ' _BUNDLED_METADATA dictionary to the library file with' + ' information on pypi name and bundled version.') + metadata = json.loads(data) + return metadata + + +def get_latest_applicable_version(pypi_data, constraints=None): + """Get the latest pypi version of the package that we allow + + :arg pypi_data: Pypi information about the data as returned by + ``https://pypi.org/pypi/{pkg_name}/json`` + :kwarg constraints: version constraints on what we're allowed to use as specified by + the bundled metadata + :returns: The most recent version on pypi that are allowed by ``constraints`` + """ + latest_version = "0" + if constraints: + version_specification = packaging.specifiers.SpecifierSet(constraints) + for version in pypi_data['releases']: + if version in version_specification: + if LooseVersion(version) > LooseVersion(latest_version): + latest_version = version + else: + latest_version = pypi_data['info']['version'] + + return latest_version + + +def main(): + """Entrypoint to the script""" + + paths = sys.argv[1:] or sys.stdin.read().splitlines() + + bundled_libs = get_bundled_libs(paths) + files_with_bundled_metadata = get_files_with_bundled_metadata(paths) + + for filename in files_with_bundled_metadata.difference(bundled_libs): + print('{0}: ERROR: File contains _BUNDLED_METADATA but needs to be added to' + ' test/sanity/code-smell/update-bundled.py'.format(filename)) + + for filename in bundled_libs: + try: + metadata = get_bundled_metadata(filename) + except ValueError as e: + print('{0}: ERROR: {1}'.format(filename, e)) + continue + except (IOError, OSError) as e: + if e.errno == 2: + print('{0}: ERROR: {1}. Perhaps the bundled library has been removed' + ' or moved and the bundled library test needs to be modified as' + ' well?'.format(filename, e)) + + pypi_fh = open_url('https://pypi.org/pypi/{0}/json'.format(metadata['pypi_name'])) + pypi_data = json.loads(pypi_fh.read().decode('utf-8')) + + constraints = metadata.get('version_constraints', None) + latest_version = get_latest_applicable_version(pypi_data, constraints) + + if LooseVersion(metadata['version']) < LooseVersion(latest_version): + print('{0}: UPDATE {1} from {2} to {3} {4}'.format( + filename, + metadata['pypi_name'], + metadata['version'], + latest_version, + 'https://pypi.org/pypi/{0}/json'.format(metadata['pypi_name']))) + + +if __name__ == '__main__': + main() diff --git a/test/sanity/code-smell/update-bundled.requirements.txt b/test/sanity/code-smell/update-bundled.requirements.txt new file mode 100644 index 00000000..748809f7 --- /dev/null +++ b/test/sanity/code-smell/update-bundled.requirements.txt @@ -0,0 +1 @@ +packaging diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt new file mode 100644 index 00000000..5275f076 --- /dev/null +++ b/test/sanity/ignore.txt @@ -0,0 +1,427 @@ +docs/bin/find-plugin-refs.py future-import-boilerplate +docs/bin/find-plugin-refs.py metaclass-boilerplate +docs/docsite/_extensions/pygments_lexer.py future-import-boilerplate +docs/docsite/_extensions/pygments_lexer.py metaclass-boilerplate +docs/docsite/_themes/sphinx_rtd_theme/__init__.py future-import-boilerplate +docs/docsite/_themes/sphinx_rtd_theme/__init__.py metaclass-boilerplate +docs/docsite/rst/dev_guide/testing/sanity/no-smart-quotes.rst no-smart-quotes +examples/play.yml shebang +examples/scripts/my_test.py shebang # example module but not in a normal module location +examples/scripts/my_test_facts.py shebang # example module but not in a normal module location +examples/scripts/my_test_info.py shebang # example module but not in a normal module location +examples/scripts/ConfigureRemotingForAnsible.ps1 pslint:PSCustomUseLiteralPath +examples/scripts/upgrade_to_ps3.ps1 pslint:PSCustomUseLiteralPath +examples/scripts/upgrade_to_ps3.ps1 pslint:PSUseApprovedVerbs +hacking/build-ansible.py shebang # only run by release engineers, Python 3.6+ required +hacking/build_library/build_ansible/announce.py compile-2.6!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/announce.py compile-2.7!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/announce.py compile-3.5!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/commands.py compile-2.6!skip # release and docs process only, 3.6+ required +hacking/build_library/build_ansible/commands.py compile-2.7!skip # release and docs process only, 3.6+ required +hacking/build_library/build_ansible/commands.py compile-3.5!skip # release and docs process only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/dump_config.py compile-2.6!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/dump_config.py compile-2.7!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/dump_config.py compile-3.5!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/dump_keywords.py compile-2.6!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/dump_keywords.py compile-2.7!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/dump_keywords.py compile-3.5!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/generate_man.py compile-2.6!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/generate_man.py compile-2.7!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/generate_man.py compile-3.5!skip # docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/porting_guide.py compile-2.6!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/porting_guide.py compile-2.7!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/porting_guide.py compile-3.5!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/release_announcement.py compile-2.6!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/release_announcement.py compile-2.7!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/release_announcement.py compile-3.5!skip # release process only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/update_intersphinx.py compile-2.6!skip # release process and docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/update_intersphinx.py compile-2.7!skip # release process and docs build only, 3.6+ required +hacking/build_library/build_ansible/command_plugins/update_intersphinx.py compile-3.5!skip # release process and docs build only, 3.6+ required +hacking/fix_test_syntax.py future-import-boilerplate +hacking/fix_test_syntax.py metaclass-boilerplate +hacking/get_library.py future-import-boilerplate +hacking/get_library.py metaclass-boilerplate +hacking/report.py future-import-boilerplate +hacking/report.py metaclass-boilerplate +hacking/return_skeleton_generator.py future-import-boilerplate +hacking/return_skeleton_generator.py metaclass-boilerplate +hacking/test-module.py future-import-boilerplate +hacking/test-module.py metaclass-boilerplate +hacking/tests/gen_distribution_version_testcase.py future-import-boilerplate +hacking/tests/gen_distribution_version_testcase.py metaclass-boilerplate +lib/ansible/cli/console.py pylint:blacklisted-name +lib/ansible/cli/scripts/ansible_cli_stub.py shebang +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:blacklisted-name +lib/ansible/executor/powershell/async_watchdog.ps1 pslint:PSCustomUseLiteralPath +lib/ansible/executor/powershell/async_wrapper.ps1 pslint:PSCustomUseLiteralPath +lib/ansible/executor/powershell/exec_wrapper.ps1 pslint:PSCustomUseLiteralPath +lib/ansible/executor/task_queue_manager.py pylint:blacklisted-name +lib/ansible/galaxy/collection.py compile-2.6!skip # 'ansible-galaxy collection' requires 2.7+ +lib/ansible/module_utils/compat/_selectors2.py future-import-boilerplate # ignore bundled +lib/ansible/module_utils/compat/_selectors2.py metaclass-boilerplate # ignore bundled +lib/ansible/module_utils/compat/_selectors2.py pylint:blacklisted-name +lib/ansible/module_utils/distro/__init__.py empty-init # breaks namespacing, bundled, do not override +lib/ansible/module_utils/distro/_distro.py future-import-boilerplate # ignore bundled +lib/ansible/module_utils/distro/_distro.py metaclass-boilerplate # ignore bundled +lib/ansible/module_utils/distro/_distro.py no-assert +lib/ansible/module_utils/distro/_distro.py pep8!skip # bundled code we don't want to modify +lib/ansible/module_utils/facts/__init__.py empty-init # breaks namespacing, deprecate and eventually remove +lib/ansible/module_utils/facts/network/linux.py pylint:blacklisted-name +lib/ansible/module_utils/facts/system/distribution.py pylint:ansible-bad-function +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.ArgvParser.psm1 pslint:PSUseApprovedVerbs +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 pslint:PSProvideCommentHelp # need to agree on best format for comment location +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 pslint:PSUseApprovedVerbs +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.FileUtil.psm1 pslint:PSCustomUseLiteralPath +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.FileUtil.psm1 pslint:PSProvideCommentHelp +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.Legacy.psm1 pslint:PSCustomUseLiteralPath +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.Legacy.psm1 pslint:PSUseApprovedVerbs +lib/ansible/module_utils/powershell/Ansible.ModuleUtils.LinkUtil.psm1 pslint:PSUseApprovedVerbs +lib/ansible/module_utils/pycompat24.py no-get-exception +lib/ansible/module_utils/six/__init__.py empty-init # breaks namespacing, bundled, do not override +lib/ansible/module_utils/six/__init__.py future-import-boilerplate # ignore bundled +lib/ansible/module_utils/six/__init__.py metaclass-boilerplate # ignore bundled +lib/ansible/module_utils/six/__init__.py no-basestring +lib/ansible/module_utils/six/__init__.py no-dict-iteritems +lib/ansible/module_utils/six/__init__.py no-dict-iterkeys +lib/ansible/module_utils/six/__init__.py no-dict-itervalues +lib/ansible/module_utils/six/__init__.py replace-urlopen +lib/ansible/module_utils/urls.py pylint:blacklisted-name +lib/ansible/module_utils/urls.py replace-urlopen +lib/ansible/modules/command.py validate-modules:doc-default-does-not-match-spec # _uses_shell is undocumented +lib/ansible/modules/command.py validate-modules:doc-missing-type +lib/ansible/modules/command.py validate-modules:nonexistent-parameter-documented +lib/ansible/modules/command.py validate-modules:parameter-list-no-elements +lib/ansible/modules/command.py validate-modules:undocumented-parameter +lib/ansible/modules/expect.py validate-modules:doc-missing-type +lib/ansible/modules/assemble.py validate-modules:nonexistent-parameter-documented +lib/ansible/modules/blockinfile.py validate-modules:doc-choices-do-not-match-spec +lib/ansible/modules/blockinfile.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/copy.py pylint:blacklisted-name +lib/ansible/modules/copy.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/copy.py validate-modules:doc-type-does-not-match-spec +lib/ansible/modules/copy.py validate-modules:nonexistent-parameter-documented +lib/ansible/modules/copy.py validate-modules:undocumented-parameter +lib/ansible/modules/file.py pylint:ansible-bad-function +lib/ansible/modules/file.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/file.py validate-modules:undocumented-parameter +lib/ansible/modules/find.py use-argspec-type-path # fix needed +lib/ansible/modules/lineinfile.py validate-modules:doc-choices-do-not-match-spec +lib/ansible/modules/lineinfile.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/lineinfile.py validate-modules:nonexistent-parameter-documented +lib/ansible/modules/replace.py validate-modules:nonexistent-parameter-documented +lib/ansible/modules/stat.py validate-modules:doc-default-does-not-match-spec # get_md5 is undocumented +lib/ansible/modules/stat.py validate-modules:parameter-invalid +lib/ansible/modules/stat.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/stat.py validate-modules:undocumented-parameter +lib/ansible/modules/unarchive.py validate-modules:nonexistent-parameter-documented +lib/ansible/modules/unarchive.py validate-modules:parameter-list-no-elements +lib/ansible/modules/get_url.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/uri.py pylint:blacklisted-name +lib/ansible/modules/uri.py validate-modules:doc-required-mismatch +lib/ansible/modules/uri.py validate-modules:parameter-list-no-elements +lib/ansible/modules/uri.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/pip.py pylint:blacklisted-name +lib/ansible/modules/pip.py validate-modules:doc-elements-mismatch +lib/ansible/modules/pip.py validate-modules:invalid-ansiblemodule-schema +lib/ansible/modules/apt.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/apt.py validate-modules:parameter-invalid +lib/ansible/modules/apt.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/apt.py validate-modules:undocumented-parameter +lib/ansible/modules/apt_key.py validate-modules:mutually_exclusive-unknown +lib/ansible/modules/apt_key.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/apt_key.py validate-modules:undocumented-parameter +lib/ansible/modules/apt_repository.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/apt_repository.py validate-modules:parameter-invalid +lib/ansible/modules/apt_repository.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/apt_repository.py validate-modules:undocumented-parameter +lib/ansible/modules/dnf.py validate-modules:doc-missing-type +lib/ansible/modules/dnf.py validate-modules:doc-required-mismatch +lib/ansible/modules/dnf.py validate-modules:parameter-invalid +lib/ansible/modules/dnf.py validate-modules:parameter-list-no-elements +lib/ansible/modules/dnf.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/dpkg_selections.py validate-modules:doc-missing-type +lib/ansible/modules/dpkg_selections.py validate-modules:doc-required-mismatch +lib/ansible/modules/package_facts.py validate-modules:doc-choices-do-not-match-spec +lib/ansible/modules/package_facts.py validate-modules:doc-missing-type +lib/ansible/modules/package_facts.py validate-modules:parameter-list-no-elements +lib/ansible/modules/rpm_key.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/yum.py pylint:blacklisted-name +lib/ansible/modules/yum.py validate-modules:doc-missing-type +lib/ansible/modules/yum.py validate-modules:parameter-invalid +lib/ansible/modules/yum.py validate-modules:parameter-list-no-elements +lib/ansible/modules/yum.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/yum_repository.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/yum_repository.py validate-modules:doc-missing-type +lib/ansible/modules/yum_repository.py validate-modules:parameter-list-no-elements +lib/ansible/modules/yum_repository.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/yum_repository.py validate-modules:undocumented-parameter +lib/ansible/modules/git.py pylint:blacklisted-name +lib/ansible/modules/git.py use-argspec-type-path +lib/ansible/modules/git.py validate-modules:doc-missing-type +lib/ansible/modules/git.py validate-modules:doc-required-mismatch +lib/ansible/modules/git.py validate-modules:parameter-list-no-elements +lib/ansible/modules/git.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/subversion.py validate-modules:doc-required-mismatch +lib/ansible/modules/subversion.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/subversion.py validate-modules:undocumented-parameter +lib/ansible/modules/getent.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/hostname.py validate-modules:invalid-ansiblemodule-schema +lib/ansible/modules/hostname.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/iptables.py pylint:blacklisted-name +lib/ansible/modules/iptables.py validate-modules:parameter-list-no-elements +lib/ansible/modules/service.py validate-modules:nonexistent-parameter-documented +lib/ansible/modules/service.py validate-modules:use-run-command-not-popen +lib/ansible/modules/setup.py validate-modules:doc-missing-type +lib/ansible/modules/setup.py validate-modules:parameter-list-no-elements +lib/ansible/modules/setup.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/systemd.py validate-modules:parameter-invalid +lib/ansible/modules/systemd.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/systemd.py validate-modules:return-syntax-error +lib/ansible/modules/sysvinit.py validate-modules:parameter-list-no-elements +lib/ansible/modules/sysvinit.py validate-modules:parameter-type-not-in-doc +lib/ansible/modules/sysvinit.py validate-modules:return-syntax-error +lib/ansible/modules/user.py validate-modules:doc-default-does-not-match-spec +lib/ansible/modules/user.py validate-modules:doc-default-incompatible-type +lib/ansible/modules/user.py validate-modules:parameter-list-no-elements +lib/ansible/modules/user.py validate-modules:use-run-command-not-popen +lib/ansible/modules/async_status.py use-argspec-type-path +lib/ansible/modules/async_status.py validate-modules!skip +lib/ansible/modules/async_wrapper.py ansible-doc!skip # not an actual module +lib/ansible/modules/async_wrapper.py pylint:ansible-bad-function +lib/ansible/modules/async_wrapper.py use-argspec-type-path +lib/ansible/modules/wait_for.py validate-modules:parameter-list-no-elements +lib/ansible/parsing/vault/__init__.py pylint:blacklisted-name +lib/ansible/playbook/base.py pylint:blacklisted-name +lib/ansible/playbook/collectionsearch.py required-and-default-attributes # https://github.com/ansible/ansible/issues/61460 +lib/ansible/playbook/helpers.py pylint:blacklisted-name +lib/ansible/playbook/role/__init__.py pylint:blacklisted-name +lib/ansible/plugins/action/normal.py action-plugin-docs # default action plugin for modules without a dedicated action plugin +lib/ansible/plugins/cache/base.py ansible-doc!skip # not a plugin, but a stub for backwards compatibility +lib/ansible/plugins/lookup/sequence.py pylint:blacklisted-name +lib/ansible/plugins/strategy/__init__.py pylint:blacklisted-name +lib/ansible/plugins/strategy/linear.py pylint:blacklisted-name +lib/ansible/vars/hostvars.py pylint:blacklisted-name +test/integration/targets/ansible-runner/files/adhoc_example1.py future-import-boilerplate +test/integration/targets/ansible-runner/files/adhoc_example1.py metaclass-boilerplate +test/integration/targets/ansible-runner/files/playbook_example1.py future-import-boilerplate +test/integration/targets/ansible-runner/files/playbook_example1.py metaclass-boilerplate +test/integration/targets/ansible-test/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import +test/integration/targets/ansible-test/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import-from +test/integration/targets/ansible-test/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py pylint:ansible-bad-function +test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/filter/check_pylint.py pylint:blacklisted-name +test/integration/targets/ansible-test/ansible_collections/ns/col/plugins/modules/hello.py pylint:relative-beyond-top-level +test/integration/targets/ansible-test/ansible_collections/ns/col/tests/unit/plugins/module_utils/test_my_util.py pylint:relative-beyond-top-level +test/integration/targets/ansible-test/ansible_collections/ns/col/tests/unit/plugins/modules/test_hello.py pylint:relative-beyond-top-level +test/integration/targets/ansible-test-docker/ansible_collections/ns/col/plugins/modules/hello.py pylint:relative-beyond-top-level +test/integration/targets/ansible-test-docker/ansible_collections/ns/col/tests/unit/plugins/module_utils/test_my_util.py pylint:relative-beyond-top-level +test/integration/targets/ansible-test-docker/ansible_collections/ns/col/tests/unit/plugins/modules/test_hello.py pylint:relative-beyond-top-level +test/integration/targets/async_fail/library/async_test.py future-import-boilerplate +test/integration/targets/async_fail/library/async_test.py metaclass-boilerplate +test/integration/targets/collections_plugin_namespace/collection_root/ansible_collections/my_ns/my_col/plugins/lookup/lookup_no_future_boilerplate.py future-import-boilerplate +test/integration/targets/collections_relative_imports/collection_root/ansible_collections/my_ns/my_col/plugins/module_utils/my_util2.py pylint:relative-beyond-top-level +test/integration/targets/collections_relative_imports/collection_root/ansible_collections/my_ns/my_col/plugins/module_utils/my_util3.py pylint:relative-beyond-top-level +test/integration/targets/collections_relative_imports/collection_root/ansible_collections/my_ns/my_col/plugins/modules/my_module.py pylint:relative-beyond-top-level +test/integration/targets/expect/files/test_command.py future-import-boilerplate +test/integration/targets/expect/files/test_command.py metaclass-boilerplate +test/integration/targets/gathering_facts/library/bogus_facts shebang +test/integration/targets/gathering_facts/library/facts_one shebang +test/integration/targets/gathering_facts/library/facts_two shebang +test/integration/targets/get_url/files/testserver.py future-import-boilerplate +test/integration/targets/get_url/files/testserver.py metaclass-boilerplate +test/integration/targets/group/files/gidget.py future-import-boilerplate +test/integration/targets/group/files/gidget.py metaclass-boilerplate +test/integration/targets/ignore_unreachable/fake_connectors/bad_exec.py future-import-boilerplate +test/integration/targets/ignore_unreachable/fake_connectors/bad_exec.py metaclass-boilerplate +test/integration/targets/ignore_unreachable/fake_connectors/bad_put_file.py future-import-boilerplate +test/integration/targets/ignore_unreachable/fake_connectors/bad_put_file.py metaclass-boilerplate +test/integration/targets/json_cleanup/library/bad_json shebang +test/integration/targets/incidental_win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xSetReboot/ANSIBLE_xSetReboot.psm1 pslint!skip +test/integration/targets/incidental_win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xTestResource/ANSIBLE_xTestResource.psm1 pslint!skip +test/integration/targets/incidental_win_dsc/files/xTestDsc/1.0.0/xTestDsc.psd1 pslint!skip +test/integration/targets/incidental_win_dsc/files/xTestDsc/1.0.1/DSCResources/ANSIBLE_xTestResource/ANSIBLE_xTestResource.psm1 pslint!skip +test/integration/targets/incidental_win_dsc/files/xTestDsc/1.0.1/xTestDsc.psd1 pslint!skip +test/integration/targets/incidental_win_ping/library/win_ping_syntax_error.ps1 pslint!skip +test/integration/targets/incidental_win_reboot/templates/post_reboot.ps1 pslint!skip +test/integration/targets/lookup_ini/lookup-8859-15.ini no-smart-quotes +test/integration/targets/module_precedence/lib_with_extension/a.ini shebang +test/integration/targets/module_precedence/lib_with_extension/ping.ini shebang +test/integration/targets/module_precedence/lib_with_extension/ping.py future-import-boilerplate +test/integration/targets/module_precedence/lib_with_extension/ping.py metaclass-boilerplate +test/integration/targets/module_precedence/multiple_roles/bar/library/ping.py future-import-boilerplate +test/integration/targets/module_precedence/multiple_roles/bar/library/ping.py metaclass-boilerplate +test/integration/targets/module_precedence/multiple_roles/foo/library/ping.py future-import-boilerplate +test/integration/targets/module_precedence/multiple_roles/foo/library/ping.py metaclass-boilerplate +test/integration/targets/module_precedence/roles_with_extension/foo/library/a.ini shebang +test/integration/targets/module_precedence/roles_with_extension/foo/library/ping.ini shebang +test/integration/targets/module_precedence/roles_with_extension/foo/library/ping.py future-import-boilerplate +test/integration/targets/module_precedence/roles_with_extension/foo/library/ping.py metaclass-boilerplate +test/integration/targets/module_utils/library/test.py future-import-boilerplate +test/integration/targets/module_utils/library/test.py metaclass-boilerplate +test/integration/targets/module_utils/library/test_env_override.py future-import-boilerplate +test/integration/targets/module_utils/library/test_env_override.py metaclass-boilerplate +test/integration/targets/module_utils/library/test_failure.py future-import-boilerplate +test/integration/targets/module_utils/library/test_failure.py metaclass-boilerplate +test/integration/targets/module_utils/library/test_override.py future-import-boilerplate +test/integration/targets/module_utils/library/test_override.py metaclass-boilerplate +test/integration/targets/module_utils/module_utils/bar0/foo.py pylint:blacklisted-name +test/integration/targets/module_utils/module_utils/foo.py pylint:blacklisted-name +test/integration/targets/module_utils/module_utils/sub/bar/__init__.py pylint:blacklisted-name +test/integration/targets/module_utils/module_utils/sub/bar/bar.py pylint:blacklisted-name +test/integration/targets/module_utils/module_utils/yak/zebra/foo.py pylint:blacklisted-name +test/integration/targets/old_style_modules_posix/library/helloworld.sh shebang +test/integration/targets/pause/test-pause.py future-import-boilerplate +test/integration/targets/pause/test-pause.py metaclass-boilerplate +test/integration/targets/pip/files/ansible_test_pip_chdir/__init__.py future-import-boilerplate +test/integration/targets/pip/files/ansible_test_pip_chdir/__init__.py metaclass-boilerplate +test/integration/targets/pip/files/setup.py future-import-boilerplate +test/integration/targets/pip/files/setup.py metaclass-boilerplate +test/integration/targets/run_modules/library/test.py future-import-boilerplate +test/integration/targets/run_modules/library/test.py metaclass-boilerplate +test/integration/targets/script/files/no_shebang.py future-import-boilerplate +test/integration/targets/script/files/no_shebang.py metaclass-boilerplate +test/integration/targets/service/files/ansible_test_service.py future-import-boilerplate +test/integration/targets/service/files/ansible_test_service.py metaclass-boilerplate +test/integration/targets/setup_rpm_repo/files/create-repo.py future-import-boilerplate +test/integration/targets/setup_rpm_repo/files/create-repo.py metaclass-boilerplate +test/integration/targets/template/files/encoding_1252_utf-8.expected no-smart-quotes +test/integration/targets/template/files/encoding_1252_windows-1252.expected no-smart-quotes +test/integration/targets/template/files/foo.dos.txt line-endings +test/integration/targets/template/role_filter/filter_plugins/myplugin.py future-import-boilerplate +test/integration/targets/template/role_filter/filter_plugins/myplugin.py metaclass-boilerplate +test/integration/targets/template/templates/encoding_1252.j2 no-smart-quotes +test/integration/targets/infra/library/test.py future-import-boilerplate +test/integration/targets/infra/library/test.py metaclass-boilerplate +test/integration/targets/unicode/unicode.yml no-smart-quotes +test/integration/targets/uri/files/testserver.py future-import-boilerplate +test/integration/targets/uri/files/testserver.py metaclass-boilerplate +test/integration/targets/var_precedence/ansible-var-precedence-check.py future-import-boilerplate +test/integration/targets/var_precedence/ansible-var-precedence-check.py metaclass-boilerplate +test/integration/targets/builtin_vars_prompt/test-vars_prompt.py future-import-boilerplate +test/integration/targets/builtin_vars_prompt/test-vars_prompt.py metaclass-boilerplate +test/integration/targets/vault/test-vault-client.py future-import-boilerplate +test/integration/targets/vault/test-vault-client.py metaclass-boilerplate +test/integration/targets/wait_for/files/testserver.py future-import-boilerplate +test/integration/targets/wait_for/files/testserver.py metaclass-boilerplate +test/integration/targets/want_json_modules_posix/library/helloworld.py future-import-boilerplate +test/integration/targets/want_json_modules_posix/library/helloworld.py metaclass-boilerplate +test/integration/targets/win_exec_wrapper/library/test_fail.ps1 pslint:PSCustomUseLiteralPath +test/integration/targets/win_exec_wrapper/tasks/main.yml no-smart-quotes # We are explicitly testing smart quote support for env vars +test/integration/targets/win_fetch/tasks/main.yml no-smart-quotes # We are explictly testing smart quotes in the file name to fetch +test/integration/targets/win_module_utils/library/legacy_only_new_way_win_line_ending.ps1 line-endings # Explicitly tests that we still work with Windows line endings +test/integration/targets/win_module_utils/library/legacy_only_old_way_win_line_ending.ps1 line-endings # Explicitly tests that we still work with Windows line endings +test/integration/targets/win_script/files/test_script.ps1 pslint:PSAvoidUsingWriteHost # Keep +test/integration/targets/win_script/files/test_script_creates_file.ps1 pslint:PSAvoidUsingCmdletAliases +test/integration/targets/win_script/files/test_script_removes_file.ps1 pslint:PSCustomUseLiteralPath +test/integration/targets/win_script/files/test_script_with_args.ps1 pslint:PSAvoidUsingWriteHost # Keep +test/integration/targets/win_script/files/test_script_with_splatting.ps1 pslint:PSAvoidUsingWriteHost # Keep +test/integration/targets/windows-minimal/library/win_ping_syntax_error.ps1 pslint!skip +test/lib/ansible_test/_data/requirements/constraints.txt test-constraints +test/lib/ansible_test/_data/requirements/integration.cloud.azure.txt test-constraints +test/lib/ansible_test/_data/requirements/sanity.ps1 pslint:PSCustomUseLiteralPath # Uses wildcards on purpose +test/lib/ansible_test/_data/sanity/pylint/plugins/string_format.py use-compat-six +test/lib/ansible_test/_data/setup/ConfigureRemotingForAnsible.ps1 pslint:PSCustomUseLiteralPath +test/lib/ansible_test/_data/setup/windows-httptester.ps1 pslint:PSCustomUseLiteralPath +test/support/integration/plugins/module_utils/azure_rm_common.py future-import-boilerplate +test/support/integration/plugins/module_utils/azure_rm_common.py metaclass-boilerplate +test/support/integration/plugins/module_utils/azure_rm_common_rest.py future-import-boilerplate +test/support/integration/plugins/module_utils/azure_rm_common_rest.py metaclass-boilerplate +test/support/integration/plugins/module_utils/cloud.py future-import-boilerplate +test/support/integration/plugins/module_utils/cloud.py metaclass-boilerplate +test/support/integration/plugins/module_utils/compat/ipaddress.py future-import-boilerplate +test/support/integration/plugins/module_utils/compat/ipaddress.py metaclass-boilerplate +test/support/integration/plugins/module_utils/compat/ipaddress.py no-unicode-literals +test/support/integration/plugins/module_utils/database.py future-import-boilerplate +test/support/integration/plugins/module_utils/database.py metaclass-boilerplate +test/support/integration/plugins/module_utils/mysql.py future-import-boilerplate +test/support/integration/plugins/module_utils/mysql.py metaclass-boilerplate +test/support/integration/plugins/module_utils/network/common/utils.py future-import-boilerplate +test/support/integration/plugins/module_utils/network/common/utils.py metaclass-boilerplate +test/support/integration/plugins/module_utils/postgres.py future-import-boilerplate +test/support/integration/plugins/module_utils/postgres.py metaclass-boilerplate +test/support/integration/plugins/modules/lvg.py pylint:blacklisted-name +test/support/integration/plugins/modules/synchronize.py pylint:blacklisted-name +test/support/integration/plugins/modules/timezone.py pylint:blacklisted-name +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/doc_fragments/netconf.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/doc_fragments/netconf.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/doc_fragments/network_agnostic.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/doc_fragments/network_agnostic.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/compat/ipaddress.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/compat/ipaddress.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/compat/ipaddress.py no-unicode-literals +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/compat/ipaddress.py pep8:E203 +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/cfg/base.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/cfg/base.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/config.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/config.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/facts/facts.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/facts/facts.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/netconf.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/netconf.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/network.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/network.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/parsing.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/parsing.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/utils.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/common/utils.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/netconf/netconf.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/netconf/netconf.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/restconf/restconf.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/module_utils/network/restconf/restconf.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/doc_fragments/ios.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/doc_fragments/ios.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/module_utils/network/ios/ios.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/module_utils/network/ios/ios.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_command.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_command.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_config.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_config.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_config.py pep8:E501 +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/doc_fragments/vyos.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/doc_fragments/vyos.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/vyos.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/vyos.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py pep8:E231 +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py pylint:blacklisted-name +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_config.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_config.py metaclass-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_facts.py future-import-boilerplate +test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_facts.py metaclass-boilerplate +test/support/windows-integration/plugins/modules/async_status.ps1 pslint!skip +test/support/windows-integration/plugins/modules/setup.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_copy.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_dsc.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_feature.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_find.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_lineinfile.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_regedit.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_security_policy.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_shell.ps1 pslint!skip +test/support/windows-integration/plugins/modules/win_wait_for.ps1 pslint!skip +test/units/executor/test_play_iterator.py pylint:blacklisted-name +test/units/module_utils/basic/test_deprecate_warn.py pylint:ansible-deprecated-no-version +test/units/module_utils/basic/test_deprecate_warn.py pylint:ansible-deprecated-version +test/units/module_utils/basic/test_run_command.py pylint:blacklisted-name +test/units/module_utils/urls/fixtures/multipart.txt line-endings # Fixture for HTTP tests that use CRLF +test/units/module_utils/urls/test_Request.py replace-urlopen +test/units/module_utils/urls/test_fetch_url.py replace-urlopen +test/units/modules/test_apt.py pylint:blacklisted-name +test/units/modules/test_known_hosts.py pylint:ansible-bad-function +test/units/parsing/vault/test_vault.py pylint:blacklisted-name +test/units/playbook/role/test_role.py pylint:blacklisted-name +test/units/plugins/test_plugins.py pylint:blacklisted-name +test/units/template/test_templar.py pylint:blacklisted-name +test/units/utils/collection_loader/fixtures/collections/ansible_collections/testns/testcoll/plugins/module_utils/my_util.py future-import-boilerplate # test expects no boilerplate +test/units/utils/collection_loader/fixtures/collections/ansible_collections/testns/testcoll/plugins/module_utils/my_util.py metaclass-boilerplate # test expects no boilerplate +test/units/utils/collection_loader/fixtures/collections/ansible_collections/testns/testcoll/plugins/action/my_action.py pylint:relative-beyond-top-level +test/units/utils/collection_loader/fixtures/collections/ansible_collections/testns/testcoll/plugins/modules/__init__.py empty-init # testing that collections don't need inits +test/units/utils/collection_loader/fixtures/collections_masked/ansible_collections/__init__.py empty-init # testing that collections don't need inits +test/units/utils/collection_loader/fixtures/collections_masked/ansible_collections/ansible/__init__.py empty-init # testing that collections don't need inits +test/units/utils/collection_loader/fixtures/collections_masked/ansible_collections/testns/__init__.py empty-init # testing that collections don't need inits +test/units/utils/collection_loader/fixtures/collections_masked/ansible_collections/testns/testcoll/__init__.py empty-init # testing that collections don't need inits +test/units/utils/collection_loader/test_collection_loader.py pylint:undefined-variable # magic runtime local var splatting +test/utils/shippable/check_matrix.py replace-urlopen +test/utils/shippable/timing.py shebang |