diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index b531cbd..13db395 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Determine matrix id: generate_matrix - uses: coactions/dynamic-matrix@v4 + uses: ansible/actions/matrix@v1 with: min_python: "3.10" max_python: "3.14" @@ -95,9 +95,9 @@ jobs: if: ${{ matrix.command5 }} - name: Archive logs - uses: coactions/upload-artifact@v4 + uses: actions/upload-artifact@v4 with: - name: logs-${{ matrix.name }}.zip + name: logs-${{ matrix.name }} include-hidden-files: true if-no-files-found: ignore path: | @@ -132,20 +132,12 @@ jobs: - run: pip3 install 'coverage>=7.5.1' - - name: Merge logs into a single archive - uses: actions/upload-artifact/merge@v4 - with: - name: logs.zip - include-hidden-files: true - pattern: logs-*.zip - # artifacts like py312.zip and py312-macos do have overlapping files - separate-directories: true - - name: Download artifacts uses: actions/download-artifact@v4 continue-on-error: true # to allow rerunning this job with: - name: logs.zip + pattern: logs-* + merge-multiple: true path: . @@ -154,7 +146,7 @@ jobs: with: name: ${{ matrix.name }} # verbose: true # optional (default = false) - fail_ci_if_error: true + fail_ci_if_error: false use_oidc: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork) }} # cspell:ignore oidc - name: Decide whether the needed jobs succeeded or failed diff --git a/.gitignore b/.gitignore index 28baac9..145029c 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,4 @@ src/doc8/_version.py .idea/ .vscode/ junit.xml +uv.lock diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a27605a..53f50e7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: - id: trailing-whitespace - id: check-executables-have-shebangs - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 + rev: v3.21.2 hooks: - id: pyupgrade - repo: https://github.com/pappasam/toml-sort diff --git a/src/doc8/checks.py b/src/doc8/checks.py index 2b6870f..77ac59f 100644 --- a/src/doc8/checks.py +++ b/src/doc8/checks.py @@ -121,6 +121,10 @@ class CheckValidity(ContentCheck): re.compile( r'^PEP number must be a number from 0 to 9999; "\d{1,4}#[^"]*" is invalid.', ), + re.compile( + r'^Error in "(?:admonition|attention|caution|danger|error|hint|important|note|tip|warning)" directive:\nunknown option: "collapsible"', + re.MULTILINE, + ), ] def __init__(self, cfg): diff --git a/src/doc8/tests/test_checks.py b/src/doc8/tests/test_checks.py index 155c1ff..b4a50cd 100644 --- a/src/doc8/tests/test_checks.py +++ b/src/doc8/tests/test_checks.py @@ -183,3 +183,26 @@ def test_newline(self): check = checks.CheckNewlineEndOfFile({}) errors = list(check.report_iter(parsed_file)) self.assertEqual(expected_errors, len(errors)) + + +class TestValidity(unittest.TestCase): + def test_collapsible_admonition_ignored_in_sphinx_mode(self): + content = b".. note::\n :collapsible:\n\n Collapsible note.\n" + with tempfile.NamedTemporaryFile(suffix=".rst") as fh: + fh.write(content) + fh.flush() + parsed_file = parser.ParsedFile(fh.name) + check = checks.CheckValidity({"sphinx": True}) + errors = list(check.report_iter(parsed_file)) + self.assertEqual(0, len(errors)) + + def test_collapsible_admonition_flagged_without_sphinx_mode(self): + content = b".. note::\n :collapsible:\n\n Collapsible note.\n" + with tempfile.NamedTemporaryFile(suffix=".rst") as fh: + fh.write(content) + fh.flush() + parsed_file = parser.ParsedFile(fh.name) + check = checks.CheckValidity({"sphinx": False}) + errors = list(check.report_iter(parsed_file)) + self.assertEqual(1, len(errors)) + self.assertEqual("D000", errors[0][1])