mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Replace tests/unit/test_doc.py
with a pre-commit hook.
We don't need to test docs on all platforms. In turn, we make the check a pre-commit hook which seems more suited.
This commit is contained in:
parent
a5b9961f78
commit
6a4703146c
5 changed files with 476 additions and 601 deletions
|
@ -598,3 +598,16 @@ repos:
|
||||||
- -e
|
- -e
|
||||||
- lint-tests-pre-commit
|
- lint-tests-pre-commit
|
||||||
- --
|
- --
|
||||||
|
|
||||||
|
- repo: https://github.com/saltstack/salt-nox-pre-commit
|
||||||
|
rev: master
|
||||||
|
hooks:
|
||||||
|
- id: nox-py2
|
||||||
|
alias: check-docs
|
||||||
|
name: Check Docs
|
||||||
|
files: ^(salt/.*\.py|doc/ref/.*\.rst)$
|
||||||
|
args:
|
||||||
|
- -e
|
||||||
|
- invoke-pre-commit
|
||||||
|
- --
|
||||||
|
- docs.check
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from invoke import Collection # pylint: disable=3rd-party-module-not-gated
|
from invoke import Collection # pylint: disable=3rd-party-module-not-gated
|
||||||
|
from . import docs
|
||||||
|
|
||||||
ns = Collection()
|
ns = Collection()
|
||||||
|
docs = Collection.from_module(docs, name="docs")
|
||||||
|
ns.add_collection(docs, name="docs")
|
||||||
|
|
459
tasks/docs.py
Normal file
459
tasks/docs.py
Normal file
|
@ -0,0 +1,459 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
tasks.docstrings
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Check salt code base for for missing or wrong docstrings
|
||||||
|
"""
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import collections
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
|
||||||
|
from invoke import task # pylint: disable=3rd-party-module-not-gated
|
||||||
|
from tasks import utils
|
||||||
|
|
||||||
|
CODE_DIR = pathlib.Path(__file__).resolve().parent.parent
|
||||||
|
DOCS_DIR = CODE_DIR / "doc"
|
||||||
|
SALT_CODE_DIR = CODE_DIR / "salt"
|
||||||
|
|
||||||
|
os.chdir(str(CODE_DIR))
|
||||||
|
|
||||||
|
python_module_to_doc_path = {}
|
||||||
|
doc_path_to_python_module = {}
|
||||||
|
|
||||||
|
|
||||||
|
check_paths = (
|
||||||
|
"salt/auth",
|
||||||
|
"salt/beacons",
|
||||||
|
"salt/cache",
|
||||||
|
"salt/cloud",
|
||||||
|
"salt/engine",
|
||||||
|
"salt/executors",
|
||||||
|
"salt/fileserver",
|
||||||
|
"salt/grains",
|
||||||
|
"salt/modules",
|
||||||
|
"salt/netapi",
|
||||||
|
"salt/output",
|
||||||
|
"salt/pillar",
|
||||||
|
"salt/proxy",
|
||||||
|
"salt/queues",
|
||||||
|
"salt/renderers",
|
||||||
|
"salt/returners",
|
||||||
|
"salt/roster",
|
||||||
|
"salt/runners",
|
||||||
|
"salt/sdb",
|
||||||
|
"salt/serializers",
|
||||||
|
"salt/states",
|
||||||
|
"salt/thorium",
|
||||||
|
"salt/tokens",
|
||||||
|
"salt/tops",
|
||||||
|
"salt/wheel",
|
||||||
|
)
|
||||||
|
exclude_paths = (
|
||||||
|
"salt/cloud/cli.py",
|
||||||
|
"salt/cloud/exceptions.py",
|
||||||
|
"salt/cloud/libcloudfuncs.py",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_path_cache():
|
||||||
|
"""
|
||||||
|
Build a python module to doc module cache
|
||||||
|
"""
|
||||||
|
|
||||||
|
for path in SALT_CODE_DIR.rglob("*.py"):
|
||||||
|
path = path.resolve().relative_to(CODE_DIR)
|
||||||
|
strpath = str(path)
|
||||||
|
if strpath.endswith("__init__.py"):
|
||||||
|
continue
|
||||||
|
if not strpath.startswith(check_paths):
|
||||||
|
continue
|
||||||
|
if strpath.startswith(exclude_paths):
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = list(path.parts)
|
||||||
|
stub_path = DOCS_DIR / "ref"
|
||||||
|
# Remove salt from parts
|
||||||
|
parts.pop(0)
|
||||||
|
# Remove the package from parts
|
||||||
|
package = parts.pop(0)
|
||||||
|
# Remove the module from parts
|
||||||
|
module = parts.pop()
|
||||||
|
|
||||||
|
if package == "cloud":
|
||||||
|
package = "clouds"
|
||||||
|
if package == "fileserver":
|
||||||
|
package = "file_server"
|
||||||
|
if package == "netapi":
|
||||||
|
# These are handled differently
|
||||||
|
if not parts:
|
||||||
|
# This is rest_wsgi
|
||||||
|
stub_path = (
|
||||||
|
stub_path
|
||||||
|
/ package
|
||||||
|
/ "all"
|
||||||
|
/ str(path).replace(".py", ".rst").replace(os.sep, ".")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# rest_cherrypy, rest_tornado
|
||||||
|
subpackage = parts.pop(0)
|
||||||
|
stub_path = (
|
||||||
|
stub_path
|
||||||
|
/ package
|
||||||
|
/ "all"
|
||||||
|
/ "salt.netapi.{}.rst".format(subpackage)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
stub_path = (
|
||||||
|
stub_path
|
||||||
|
/ package
|
||||||
|
/ "all"
|
||||||
|
/ str(path).replace(".py", ".rst").replace(os.sep, ".")
|
||||||
|
)
|
||||||
|
stub_path = stub_path.relative_to(CODE_DIR)
|
||||||
|
python_module_to_doc_path[path] = stub_path
|
||||||
|
doc_path_to_python_module[stub_path] = path
|
||||||
|
|
||||||
|
|
||||||
|
build_path_cache()
|
||||||
|
|
||||||
|
|
||||||
|
def build_file_list(files, extension):
|
||||||
|
# Unfortunately invoke does not support nargs.
|
||||||
|
# We migth have been passed --files="foo.py bar.py"
|
||||||
|
# Turn that into a list of paths
|
||||||
|
_files = []
|
||||||
|
for path in files:
|
||||||
|
if not path:
|
||||||
|
continue
|
||||||
|
for spath in path.split():
|
||||||
|
if not spath.endswith(extension):
|
||||||
|
continue
|
||||||
|
_files.append(spath)
|
||||||
|
if not _files:
|
||||||
|
_files = CODE_DIR.rglob("*{}".format(extension))
|
||||||
|
else:
|
||||||
|
_files = [pathlib.Path(fname) for fname in _files]
|
||||||
|
_files = [path.relative_to(CODE_DIR) for path in _files]
|
||||||
|
return _files
|
||||||
|
|
||||||
|
|
||||||
|
def build_python_module_paths(files):
|
||||||
|
_files = []
|
||||||
|
for path in build_file_list(files, ".py"):
|
||||||
|
strpath = str(path)
|
||||||
|
if strpath.endswith("__init__.py"):
|
||||||
|
continue
|
||||||
|
if not strpath.startswith(check_paths):
|
||||||
|
continue
|
||||||
|
if strpath.startswith(exclude_paths):
|
||||||
|
continue
|
||||||
|
_files.append(path)
|
||||||
|
return _files
|
||||||
|
|
||||||
|
|
||||||
|
def build_docs_paths(files):
|
||||||
|
return build_file_list(files, ".rst")
|
||||||
|
|
||||||
|
|
||||||
|
@task(iterable=["files"], positional=["files"])
|
||||||
|
def check_inline_markup(ctx, files):
|
||||||
|
"""
|
||||||
|
Check docstring for :doc: usage
|
||||||
|
|
||||||
|
We should not be using the ``:doc:`` inline markup option when
|
||||||
|
cross-referencing locations. Use ``:ref:`` or ``:mod:`` instead.
|
||||||
|
|
||||||
|
This task checks for reference to ``:doc:`` usage.
|
||||||
|
|
||||||
|
See Issue #12788 for more information.
|
||||||
|
|
||||||
|
https://github.com/saltstack/salt/issues/12788
|
||||||
|
"""
|
||||||
|
# CD into Salt's repo root directory
|
||||||
|
ctx.cd(CODE_DIR)
|
||||||
|
|
||||||
|
files = build_python_module_paths(files)
|
||||||
|
|
||||||
|
exitcode = 0
|
||||||
|
for path in files:
|
||||||
|
module = ast.parse(path.read_text(), filename=str(path))
|
||||||
|
funcdefs = [node for node in module.body if isinstance(node, ast.FunctionDef)]
|
||||||
|
for funcdef in funcdefs:
|
||||||
|
docstring = ast.get_docstring(funcdef, clean=True)
|
||||||
|
if not docstring:
|
||||||
|
continue
|
||||||
|
if ":doc:" in docstring:
|
||||||
|
utils.error(
|
||||||
|
"The {} function in {} contains ':doc:' usage", funcdef.name, path
|
||||||
|
)
|
||||||
|
exitcode += 1
|
||||||
|
utils.exit_invoke(exitcode)
|
||||||
|
|
||||||
|
|
||||||
|
@task(iterable=["files"])
|
||||||
|
def check_stubs(ctx, files):
|
||||||
|
# CD into Salt's repo root directory
|
||||||
|
ctx.cd(CODE_DIR)
|
||||||
|
|
||||||
|
files = build_python_module_paths(files)
|
||||||
|
|
||||||
|
exitcode = 0
|
||||||
|
for path in files:
|
||||||
|
strpath = str(path)
|
||||||
|
if strpath.endswith("__init__.py"):
|
||||||
|
continue
|
||||||
|
if not strpath.startswith(check_paths):
|
||||||
|
continue
|
||||||
|
if strpath.startswith(exclude_paths):
|
||||||
|
continue
|
||||||
|
stub_path = python_module_to_doc_path[path]
|
||||||
|
if not stub_path.exists():
|
||||||
|
exitcode += 1
|
||||||
|
utils.error(
|
||||||
|
"The module at {} does not have a sphinx stub at {}", path, stub_path
|
||||||
|
)
|
||||||
|
utils.exit_invoke(exitcode)
|
||||||
|
|
||||||
|
|
||||||
|
@task(iterable=["files"])
|
||||||
|
def check_virtual(ctx, files):
|
||||||
|
"""
|
||||||
|
Check if .rst files for each module contains the text ".. _virtual"
|
||||||
|
indicating it is a virtual doc page, and, in case a module exists by
|
||||||
|
the same name, it's going to be shaddowed and not accessible
|
||||||
|
"""
|
||||||
|
exitcode = 0
|
||||||
|
files = build_docs_paths(files)
|
||||||
|
for path in files:
|
||||||
|
if path.name == "index.rst":
|
||||||
|
continue
|
||||||
|
contents = path.read_text()
|
||||||
|
if ".. _virtual-" in contents:
|
||||||
|
try:
|
||||||
|
python_module = doc_path_to_python_module[path]
|
||||||
|
utils.error(
|
||||||
|
"The doc file at {} indicates that it's virtual, yet, there's a python module "
|
||||||
|
"at {} that will shaddow it.",
|
||||||
|
path,
|
||||||
|
python_module,
|
||||||
|
)
|
||||||
|
exitcode += 1
|
||||||
|
except KeyError:
|
||||||
|
# This is what we're expecting
|
||||||
|
continue
|
||||||
|
utils.exit_invoke(exitcode)
|
||||||
|
|
||||||
|
|
||||||
|
@task(iterable=["files"])
|
||||||
|
def check_module_indexes(ctx, files):
|
||||||
|
exitcode = 0
|
||||||
|
files = build_docs_paths(files)
|
||||||
|
for path in files:
|
||||||
|
if path.name != "index.rst":
|
||||||
|
continue
|
||||||
|
contents = path.read_text()
|
||||||
|
if ".. autosummary::" not in contents:
|
||||||
|
continue
|
||||||
|
module_index_block = re.search(
|
||||||
|
r"""
|
||||||
|
\.\.\s+autosummary::\s*\n
|
||||||
|
(\s+:[a-z]+:.*\n)*
|
||||||
|
(\s*\n)+
|
||||||
|
(?P<mods>(\s*[a-z0-9_\.]+\s*\n)+)
|
||||||
|
""",
|
||||||
|
contents,
|
||||||
|
flags=re.VERBOSE,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not module_index_block:
|
||||||
|
continue
|
||||||
|
|
||||||
|
module_index = re.findall(
|
||||||
|
r"""\s*([a-z0-9_\.]+)\s*\n""", module_index_block.group("mods")
|
||||||
|
)
|
||||||
|
if module_index != sorted(module_index):
|
||||||
|
exitcode += 1
|
||||||
|
utils.error(
|
||||||
|
"The autosummary mods in {} are not properly sorted. Please sort them.",
|
||||||
|
path,
|
||||||
|
)
|
||||||
|
|
||||||
|
module_index_duplicates = [
|
||||||
|
mod for mod, count in collections.Counter(module_index).items() if count > 1
|
||||||
|
]
|
||||||
|
if module_index_duplicates:
|
||||||
|
exitcode += 1
|
||||||
|
utils.error(
|
||||||
|
"Module index {} contains duplicates: {}", path, module_index_duplicates
|
||||||
|
)
|
||||||
|
# Let's check if all python modules are included in the index
|
||||||
|
path_parts = list(path.parts)
|
||||||
|
# drop doc
|
||||||
|
path_parts.pop(0)
|
||||||
|
# drop ref
|
||||||
|
path_parts.pop(0)
|
||||||
|
# drop "index.rst"
|
||||||
|
path_parts.pop()
|
||||||
|
# drop "all"
|
||||||
|
path_parts.pop()
|
||||||
|
package = path_parts.pop(0)
|
||||||
|
if package == "clouds":
|
||||||
|
package = "cloud"
|
||||||
|
if package == "file_server":
|
||||||
|
package = "fileserver"
|
||||||
|
if package == "configuration":
|
||||||
|
package = "log"
|
||||||
|
path_parts = ["handlers"]
|
||||||
|
python_package = SALT_CODE_DIR.joinpath(package, *path_parts).relative_to(
|
||||||
|
CODE_DIR
|
||||||
|
)
|
||||||
|
modules = set()
|
||||||
|
for module in python_package.rglob("*.py"):
|
||||||
|
if package == "netapi":
|
||||||
|
if module.stem == "__init__":
|
||||||
|
continue
|
||||||
|
if len(module.parts) > 4:
|
||||||
|
continue
|
||||||
|
if len(module.parts) > 3:
|
||||||
|
modules.add(module.parent.stem)
|
||||||
|
else:
|
||||||
|
modules.add(module.stem)
|
||||||
|
elif package == "cloud":
|
||||||
|
if len(module.parts) < 4:
|
||||||
|
continue
|
||||||
|
if module.name == "__init__.py":
|
||||||
|
continue
|
||||||
|
modules.add(module.stem)
|
||||||
|
elif package == "modules":
|
||||||
|
if len(module.parts) > 3:
|
||||||
|
# salt.modules.inspeclib
|
||||||
|
if module.name == "__init__.py":
|
||||||
|
modules.add(module.parent.stem)
|
||||||
|
continue
|
||||||
|
modules.add("{}.{}".format(module.parent.stem, module.stem))
|
||||||
|
continue
|
||||||
|
if module.name == "__init__.py":
|
||||||
|
continue
|
||||||
|
modules.add(module.stem)
|
||||||
|
elif module.name == "__init__.py":
|
||||||
|
continue
|
||||||
|
elif module.name != "__init__.py":
|
||||||
|
modules.add(module.stem)
|
||||||
|
|
||||||
|
missing_modules_in_index = set(modules) - set(module_index)
|
||||||
|
if missing_modules_in_index:
|
||||||
|
exitcode += 1
|
||||||
|
utils.error(
|
||||||
|
"The module index at {} is missing the following modules: {}",
|
||||||
|
path,
|
||||||
|
", ".join(missing_modules_in_index),
|
||||||
|
)
|
||||||
|
extra_modules_in_index = set(module_index) - set(modules)
|
||||||
|
if extra_modules_in_index:
|
||||||
|
exitcode += 1
|
||||||
|
utils.error(
|
||||||
|
"The module index at {} has extra modules(non existing): {}",
|
||||||
|
path,
|
||||||
|
", ".join(extra_modules_in_index),
|
||||||
|
)
|
||||||
|
utils.exit_invoke(exitcode)
|
||||||
|
|
||||||
|
|
||||||
|
@task(iterable=["files"])
|
||||||
|
def check_stray(ctx, files):
|
||||||
|
exitcode = 0
|
||||||
|
exclude_paths = (
|
||||||
|
DOCS_DIR / "_inc",
|
||||||
|
DOCS_DIR / "ref" / "cli" / "_includes",
|
||||||
|
DOCS_DIR / "ref" / "cli",
|
||||||
|
DOCS_DIR / "ref" / "configuration",
|
||||||
|
DOCS_DIR / "ref" / "file_server" / "backends.rst",
|
||||||
|
DOCS_DIR / "ref" / "file_server" / "environments.rst",
|
||||||
|
DOCS_DIR / "ref" / "file_server" / "file_roots.rst",
|
||||||
|
DOCS_DIR / "ref" / "internals",
|
||||||
|
DOCS_DIR / "ref" / "modules" / "all" / "salt.modules.inspectlib.rst",
|
||||||
|
DOCS_DIR / "ref" / "peer.rst",
|
||||||
|
DOCS_DIR / "ref" / "publisheracl.rst",
|
||||||
|
DOCS_DIR / "ref" / "python-api.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "aggregate.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "altering_states.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "backup_mode.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "compiler_ordering.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "extend.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "failhard.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "global_state_arguments.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "highstate.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "include.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "layers.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "master_side.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "ordering.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "parallel.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "providers.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "requisites.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "startup.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "testing.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "top.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "vars.rst",
|
||||||
|
DOCS_DIR / "ref" / "states" / "writing.rst",
|
||||||
|
DOCS_DIR / "topics",
|
||||||
|
)
|
||||||
|
exclude_paths = tuple([str(p.relative_to(CODE_DIR)) for p in exclude_paths])
|
||||||
|
files = build_docs_paths(files)
|
||||||
|
for path in files:
|
||||||
|
if not str(path).startswith(str((DOCS_DIR / "ref").relative_to(CODE_DIR))):
|
||||||
|
continue
|
||||||
|
if str(path).startswith(exclude_paths):
|
||||||
|
continue
|
||||||
|
if path.name in ("index.rst", "glossary.rst", "faq.rst", "README.rst"):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
python_module = doc_path_to_python_module[path]
|
||||||
|
except KeyError:
|
||||||
|
contents = path.read_text()
|
||||||
|
if ".. _virtual-" in contents:
|
||||||
|
continue
|
||||||
|
exitcode += 1
|
||||||
|
utils.error(
|
||||||
|
"The doc at {} doesn't have a corresponding python module an is considered a stray "
|
||||||
|
"doc. Please remove it.",
|
||||||
|
path,
|
||||||
|
)
|
||||||
|
utils.exit_invoke(exitcode)
|
||||||
|
|
||||||
|
|
||||||
|
@task(iterable=["files"])
|
||||||
|
def check(ctx, files):
|
||||||
|
try:
|
||||||
|
utils.info("Checking inline :doc: markup")
|
||||||
|
check_inline_markup(ctx, files)
|
||||||
|
except SystemExit as exc:
|
||||||
|
if exc.code != 0:
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
utils.info("Checking python module stubs")
|
||||||
|
check_stubs(ctx, files)
|
||||||
|
except SystemExit as exc:
|
||||||
|
if exc.code != 0:
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
utils.info("Checking virtual modules")
|
||||||
|
check_virtual(ctx, files)
|
||||||
|
except SystemExit as exc:
|
||||||
|
if exc.code != 0:
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
utils.info("Checking doc module indexes")
|
||||||
|
check_module_indexes(ctx, files)
|
||||||
|
except SystemExit as exc:
|
||||||
|
if exc.code != 0:
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
utils.info("Checking stray docs")
|
||||||
|
check_stray(ctx, files)
|
||||||
|
except SystemExit as exc:
|
||||||
|
if exc.code != 0:
|
||||||
|
raise
|
|
@ -2,6 +2,7 @@
|
||||||
"""
|
"""
|
||||||
tasks.utils
|
tasks.utils
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
Invoke utilities
|
Invoke utilities
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -1,601 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
tests.unit.doc_test
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Import Python libs
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import collections
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
|
|
||||||
# Import Salt libs
|
|
||||||
import salt.modules.cmdmod
|
|
||||||
import salt.utils.files
|
|
||||||
import salt.utils.platform
|
|
||||||
from tests.support.runtests import RUNTIME_VARS
|
|
||||||
|
|
||||||
# Import Salt Testing libs
|
|
||||||
from tests.support.unit import TestCase, skipIf
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class DocTestCase(TestCase):
|
|
||||||
"""
|
|
||||||
Unit test case for testing doc files and strings.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@skipIf(True, "SLOWTEST skip")
|
|
||||||
def test_check_for_doc_inline_markup(self):
|
|
||||||
"""
|
|
||||||
We should not be using the ``:doc:`` inline markup option when
|
|
||||||
cross-referencing locations. Use ``:ref:`` or ``:mod:`` instead.
|
|
||||||
|
|
||||||
This test checks for reference to ``:doc:`` usage.
|
|
||||||
|
|
||||||
See Issue #12788 for more information.
|
|
||||||
|
|
||||||
https://github.com/saltstack/salt/issues/12788
|
|
||||||
"""
|
|
||||||
salt_dir = RUNTIME_VARS.CODE_DIR
|
|
||||||
|
|
||||||
if salt.utils.platform.is_windows():
|
|
||||||
if salt.utils.path.which("bash"):
|
|
||||||
# Use grep from git-bash when it exists.
|
|
||||||
cmd = "bash -c 'grep -r :doc: ./salt/"
|
|
||||||
grep_call = salt.modules.cmdmod.run_stdout(cmd=cmd, cwd=salt_dir).split(
|
|
||||||
os.linesep
|
|
||||||
)
|
|
||||||
os_sep = "/"
|
|
||||||
else:
|
|
||||||
# No grep in Windows, use findstr
|
|
||||||
# findstr in windows doesn't prepend 'Binary` to binary files, so
|
|
||||||
# use the '/P' switch to skip files with unprintable characters
|
|
||||||
cmd = 'findstr /C:":doc:" /S /P {0}\\*'.format(salt_dir)
|
|
||||||
grep_call = salt.modules.cmdmod.run_stdout(cmd=cmd).split(os.linesep)
|
|
||||||
os_sep = os.sep
|
|
||||||
else:
|
|
||||||
salt_dir += "/"
|
|
||||||
cmd = "grep -r :doc: " + salt_dir
|
|
||||||
grep_call = salt.modules.cmdmod.run_stdout(cmd=cmd).split(os.linesep)
|
|
||||||
os_sep = os.sep
|
|
||||||
|
|
||||||
test_ret = {}
|
|
||||||
for line in grep_call:
|
|
||||||
# Skip any .pyc files that may be present
|
|
||||||
if line.startswith("Binary"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Only split on colons not followed by a '\' as is the case with
|
|
||||||
# Windows Drives
|
|
||||||
regex = re.compile(r":(?!\\)")
|
|
||||||
try:
|
|
||||||
key, val = regex.split(line, 1)
|
|
||||||
except ValueError:
|
|
||||||
log.error("Could not split line: %s", line)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Don't test man pages, this file, the tox or nox virtualenv files,
|
|
||||||
# the page that documents to not use ":doc:", the doc/conf.py file
|
|
||||||
# or the artifacts directory on nox CI test runs
|
|
||||||
if (
|
|
||||||
"man" in key
|
|
||||||
or ".tox{}".format(os_sep) in key
|
|
||||||
or ".nox{}".format(os_sep) in key
|
|
||||||
or "ext{}".format(os_sep) in key
|
|
||||||
or "artifacts{}".format(os_sep) in key
|
|
||||||
or key.endswith("test_doc.py")
|
|
||||||
or key.endswith(os_sep.join(["doc", "conf.py"]))
|
|
||||||
or key.endswith(os_sep.join(["conventions", "documentation.rst"]))
|
|
||||||
or key.endswith(
|
|
||||||
os_sep.join(["doc", "topics", "releases", "2016.11.2.rst"])
|
|
||||||
)
|
|
||||||
or key.endswith(
|
|
||||||
os_sep.join(["doc", "topics", "releases", "2016.11.3.rst"])
|
|
||||||
)
|
|
||||||
or key.endswith(
|
|
||||||
os_sep.join(["doc", "topics", "releases", "2016.3.5.rst"])
|
|
||||||
)
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Set up test return dict
|
|
||||||
if test_ret.get(key) is None:
|
|
||||||
test_ret[key] = [val.strip()]
|
|
||||||
else:
|
|
||||||
test_ret[key].append(val.strip())
|
|
||||||
|
|
||||||
# Allow test results to show files with :doc: ref, rather than truncating
|
|
||||||
self.maxDiff = None
|
|
||||||
|
|
||||||
# test_ret should be empty, otherwise there are :doc: references present
|
|
||||||
self.assertEqual(test_ret, {})
|
|
||||||
|
|
||||||
def _check_doc_files(self, module_skip, module_dir, doc_skip, module_doc_dir):
|
|
||||||
"""
|
|
||||||
Ensure various salt modules have associated documentation
|
|
||||||
"""
|
|
||||||
|
|
||||||
salt_dir = RUNTIME_VARS.CODE_DIR
|
|
||||||
|
|
||||||
# Build list of module files
|
|
||||||
module_files = []
|
|
||||||
skip_module_files = module_skip
|
|
||||||
full_module_dir = os.path.join(salt_dir, *module_dir)
|
|
||||||
for file in os.listdir(full_module_dir):
|
|
||||||
if file.endswith(".py"):
|
|
||||||
module_name = os.path.splitext(file)[0]
|
|
||||||
if module_name not in skip_module_files:
|
|
||||||
module_files.append(module_name)
|
|
||||||
# Capture modules in subdirectories like inspectlib and rest_cherrypy
|
|
||||||
elif (
|
|
||||||
os.path.isdir(os.path.join(full_module_dir, file))
|
|
||||||
and not file.startswith("_")
|
|
||||||
and os.path.isfile(os.path.join(full_module_dir, file, "__init__.py"))
|
|
||||||
):
|
|
||||||
module_name = file
|
|
||||||
if module_name not in skip_module_files:
|
|
||||||
module_files.append(module_name)
|
|
||||||
|
|
||||||
# Build list of documentation files
|
|
||||||
module_docs = []
|
|
||||||
skip_doc_files = doc_skip
|
|
||||||
full_module_doc_dir = os.path.join(salt_dir, *module_doc_dir)
|
|
||||||
doc_prefix = ".".join(module_dir) + "."
|
|
||||||
for file in os.listdir(full_module_doc_dir):
|
|
||||||
if file.endswith(".rst"):
|
|
||||||
doc_name = os.path.splitext(file)[0]
|
|
||||||
if doc_name.startswith(doc_prefix):
|
|
||||||
doc_name = doc_name[len(doc_prefix) :]
|
|
||||||
if doc_name not in skip_doc_files:
|
|
||||||
module_docs.append(doc_name)
|
|
||||||
|
|
||||||
module_index_file = os.path.join(full_module_doc_dir, "index.rst")
|
|
||||||
with salt.utils.files.fopen(module_index_file, "rb") as fp:
|
|
||||||
module_index_contents = fp.read().decode("utf-8")
|
|
||||||
|
|
||||||
module_index_block = re.search(
|
|
||||||
r"""
|
|
||||||
\.\.\s+autosummary::\s*\n
|
|
||||||
(\s+:[a-z]+:.*\n)*
|
|
||||||
(\s*\n)+
|
|
||||||
(?P<mods>(\s*[a-z0-9_\.]+\s*\n)+)
|
|
||||||
""",
|
|
||||||
module_index_contents,
|
|
||||||
flags=re.VERBOSE,
|
|
||||||
)
|
|
||||||
|
|
||||||
module_index = re.findall(
|
|
||||||
r"""\s*([a-z0-9_\.]+)\s*\n""", module_index_block.group("mods")
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check that every module has associated documentation file
|
|
||||||
for module in module_files:
|
|
||||||
self.assertIn(
|
|
||||||
module,
|
|
||||||
module_docs,
|
|
||||||
"module file {0} is missing documentation in {1}".format(
|
|
||||||
module, full_module_doc_dir
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check that every module is listed in the index file
|
|
||||||
self.assertIn(
|
|
||||||
module,
|
|
||||||
module_index,
|
|
||||||
"module file {0} is missing in {1}".format(module, module_index_file),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check if .rst file for this module contains the text
|
|
||||||
# ".. _virtual" indicating it is a virtual doc page
|
|
||||||
full_module_doc_name = os.path.join(
|
|
||||||
full_module_doc_dir, doc_prefix + module + ".rst"
|
|
||||||
)
|
|
||||||
with salt.utils.files.fopen(full_module_doc_name) as rst_file:
|
|
||||||
rst_text = rst_file.read()
|
|
||||||
virtual_string = 'module file "{0}" is also a virtual doc page {1} and is not accessible'
|
|
||||||
self.assertNotIn(
|
|
||||||
".. _virtual",
|
|
||||||
rst_text,
|
|
||||||
virtual_string.format(module, doc_prefix + module + ".rst"),
|
|
||||||
)
|
|
||||||
|
|
||||||
for doc_file in module_docs:
|
|
||||||
self.assertIn(
|
|
||||||
doc_file,
|
|
||||||
module_files,
|
|
||||||
"Doc file {0} is missing associated module in {1}".format(
|
|
||||||
doc_file, full_module_dir
|
|
||||||
),
|
|
||||||
)
|
|
||||||
# Check that a module index is sorted
|
|
||||||
sorted_module_index = sorted(module_index)
|
|
||||||
self.assertEqual(
|
|
||||||
module_index,
|
|
||||||
sorted_module_index,
|
|
||||||
msg="Module index is not sorted: {}".format(module_index_file),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check for duplicates inside of a module index
|
|
||||||
module_index_duplicates = [
|
|
||||||
mod for mod, count in collections.Counter(module_index).items() if count > 1
|
|
||||||
]
|
|
||||||
if module_index_duplicates:
|
|
||||||
self.fail(
|
|
||||||
"Module index {0} contains duplicates: {1}".format(
|
|
||||||
module_index_file, module_index_duplicates
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check for stray module docs
|
|
||||||
# Do not check files listed in doc_skip
|
|
||||||
stray_modules = set(module_index).difference(module_files + doc_skip)
|
|
||||||
if stray_modules:
|
|
||||||
self.fail(
|
|
||||||
"Stray module names {0} in the doc index {1}".format(
|
|
||||||
sorted(list(stray_modules)), module_index_file
|
|
||||||
)
|
|
||||||
)
|
|
||||||
stray_modules = set(module_docs).difference(module_files)
|
|
||||||
if stray_modules:
|
|
||||||
self.fail(
|
|
||||||
"Stray module doc files {0} in the doc folder {1}".format(
|
|
||||||
sorted(list(stray_modules)), full_module_doc_dir
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_auth_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure auth modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/auth/all/salt.auth.rest.rst
|
|
||||||
auth module example: salt/auth/rest.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "auth"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "auth", "all"]
|
|
||||||
self._check_doc_files(skip_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_beacon_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure beacon modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/beacons/all/salt.beacon.rest.rst
|
|
||||||
beacon module example: salt/beacons/rest.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "beacons"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "beacons", "all"]
|
|
||||||
self._check_doc_files(skip_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_cache_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure cache modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/cache/all/salt.cache.consul.rst
|
|
||||||
cache module example: salt/cache/consul.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "cache"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "cache", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_cloud_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure cloud modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/clouds/all/salt.cloud.gce.rst
|
|
||||||
cloud module example: salt/cloud/clouds/gce.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "cloud", "clouds"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "clouds", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_engine_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure engine modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/engines/all/salt.engines.docker_events.rst
|
|
||||||
engine module example: salt/engines/docker_events.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "engines"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "engines", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_executors_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure executor modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/executors/all/salt.executors.docker.rst
|
|
||||||
engine module example: salt/executors/docker.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "executors"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "executors", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_fileserver_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure fileserver modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/fileserver/all/salt.fileserver.gitfs.rst
|
|
||||||
module example: salt/fileserver/gitfs.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "fileserver"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "file_server", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_grain_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure grain modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/grains/all/salt.grains.core.rst
|
|
||||||
module example: salt/grains/core.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "grains"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "grains", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_module_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/modules/all/salt.modules.zabbix.rst
|
|
||||||
execution module example: salt/modules/zabbix.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "modules"]
|
|
||||||
skip_doc_files = [
|
|
||||||
"index",
|
|
||||||
"group",
|
|
||||||
"inspectlib.collector",
|
|
||||||
"inspectlib.dbhandle",
|
|
||||||
"inspectlib.entities",
|
|
||||||
"inspectlib.exceptions",
|
|
||||||
"inspectlib.fsdb",
|
|
||||||
"inspectlib.kiwiproc",
|
|
||||||
"inspectlib.query",
|
|
||||||
"kernelpkg",
|
|
||||||
"pkg",
|
|
||||||
"user",
|
|
||||||
"service",
|
|
||||||
"shadow",
|
|
||||||
"sysctl",
|
|
||||||
]
|
|
||||||
doc_dir = ["doc", "ref", "modules", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_netapi_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure netapi modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/netapi/all/salt.netapi.rest_cherrypy.rst
|
|
||||||
module example: salt/netapi/rest_cherrypy
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "netapi"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "netapi", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_output_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure output modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/output/all/salt.output.highstate.rst
|
|
||||||
module example: salt/output/highstate.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "output"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "output", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_pillar_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure pillar modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/pillar/all/salt.pillar.cobbler.rst
|
|
||||||
module example: salt/pillar/cobbler.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "pillar"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "pillar", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_proxy_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure proxy modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/proxy/all/salt.proxy.docker.rst
|
|
||||||
module example: salt/proxy/docker.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "proxy"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "proxy", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_queues_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure queue modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/queues/all/salt.queues.sqlite_queue.rst
|
|
||||||
module example: salt/queues/sqlite_queue.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "queues"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "queues", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_renderers_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure render modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/renderers/all/salt.renderers.json.rst
|
|
||||||
module example: salt/renderers/json.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "renderers"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "renderers", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_returners_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure return modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/returners/all/salt.returners.cassandra_return.rst
|
|
||||||
module example: salt/returners/cassandra_return.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "returners"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "returners", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_runners_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure runner modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/runners/all/salt.runners.auth.rst
|
|
||||||
module example: salt/runners/auth.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "runners"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "runners", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_sdb_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure sdb modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/sdb/all/salt.sdb.rest.rst
|
|
||||||
module example: salt/sdb/rest.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "sdb"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "sdb", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_serializers_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure serializer modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/serializers/all/salt.serializers.yaml.rst
|
|
||||||
module example: salt/serializers/yaml.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "serializers"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "serializers", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_states_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure states have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/states/all/salt.states.zabbix_host.rst
|
|
||||||
module example: salt/states/zabbix_host.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "states"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "states", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_thorium_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure thorium modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/thorium/all/salt.thorium.calc.rst
|
|
||||||
module example: salt/thorium/calc.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "thorium"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "thorium", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_token_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure token modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/tokens/all/salt.tokens.localfs.rst
|
|
||||||
module example: salt/tokens/localfs.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "tokens"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "tokens", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_tops_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure top modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/tops/all/salt.tops.saltclass.rst
|
|
||||||
module example: salt/tops/saltclass.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "tops"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "tops", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
||||||
|
|
||||||
def test_wheel_doc_files(self):
|
|
||||||
"""
|
|
||||||
Ensure wheel modules have associated documentation
|
|
||||||
|
|
||||||
doc example: doc/ref/wheel/all/salt.wheel.key.rst
|
|
||||||
module example: salt/wheel/key.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
skip_module_files = ["__init__"]
|
|
||||||
module_dir = ["salt", "wheel"]
|
|
||||||
skip_doc_files = ["index", "all"]
|
|
||||||
doc_dir = ["doc", "ref", "wheel", "all"]
|
|
||||||
self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)
|
|
Loading…
Add table
Reference in a new issue