Skip to content

Commit

Permalink
Merge pull request #1999 from ewels/readd-redundant-readme-yaml-linting
Browse files Browse the repository at this point in the history
Reintroduce linting of `docs/modules/*.md`
  • Loading branch information
ewels authored Aug 23, 2023
2 parents 9b758a5 + e4bbc69 commit fe1fbb6
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
3 changes: 2 additions & 1 deletion multiqc/multiqc.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from rich.syntax import Syntax

from .plots import table
from .utils import config, log, megaqc, plugin_hooks, report, util_functions
from .utils import config, lint_helpers, log, megaqc, plugin_hooks, report, util_functions

# Set up logging
start_execution_time = time.time()
Expand Down Expand Up @@ -432,6 +432,7 @@ def run(
config.plots_force_interactive = True
if lint:
config.lint = True
lint_helpers.run_tests()
if make_pdf:
config.template = "simple"
if no_megaqc_upload:
Expand Down
78 changes: 78 additions & 0 deletions multiqc/utils/lint_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env python

""" MultiQC lint helpers. Simple additional tests to run when
--lint is specified (outside scope of normal functions) """


import glob
import os

import yaml

from multiqc.utils import config, report

logger = config.logger


def run_tests():
"""Run all lint tests"""
if config.lint:
check_mods_docs_readme()


def lint_error(msg):
"""Add a lint error to the report"""
logger.error(msg)
report.lint_errors.append(msg)


def check_mods_docs_readme():
"""Check that all modules are listed in the YAML index
at the top of docs/README.md"""

docs_mods = []

docs_dir = os.path.join(os.path.dirname(config.MULTIQC_DIR), "docs", "modules")
if not os.path.isdir(docs_dir) and os.environ.get("GITHUB_WORKSPACE"):
docs_dir = os.path.join(os.environ.get("GITHUB_WORKSPACE"), "docs", "modules")
if not os.path.isdir(docs_dir):
logger.warning(f"Can't check docs readmes in lint test as directory doesn't exist: {docs_dir}")
return None

for fn in glob.glob(os.path.join(docs_dir, "*.md")):
docs_mods.append(os.path.basename(fn)[:-3])
logger.info(f"Checking docs readmes in '{docs_dir}' as --lint specified")

# Check that installed modules are listed in docs/modules
for m in config.avail_modules.keys():
if m not in docs_mods and m != "custom_content":
lint_error(f"LINT: Module '{m}' found in installed modules, but not docs/modules")

# Check that modules in docs/modules are installed
for m in docs_mods:
if m not in config.avail_modules.keys() and m != "custom_content":
lint_error(f"LINT: Module '{m}' found in docs/modules, but not installed modules")

# Check that all modules have a YAML header conforming to the required structure
for fn in glob.glob(os.path.join(docs_dir, "*.md")):
with open(fn) as fh:
# Load the YAML header from the markdown file. YAML header should be placed between --- and --- in the beginning of the file
try:
header = fh.read().split("---")[1]
except IndexError:
lint_error(f"LINT: '{fn}' doesn't have a YAML header between '---'")
continue
try:
header = yaml.safe_load(header)
except yaml.YAMLError as e:
lint_error(f"LINT: '{fn}' contains an incorrectly formatted YAML header: {e}")
continue
if header is None:
lint_error(f"LINT: '{fn}' contains an empty YAML header")
continue
req_fields = ["name", "url", "description"]
for field in req_fields:
if field not in header:
lint_error(
f"LINT: the YAML header in '{fn}' does not have a '{field}' field. Required fields: {req_fields}"
)

0 comments on commit fe1fbb6

Please sign in to comment.