Skip to content

fix: dedent PathSpec config values before compiling patterns - #4208

Open
Manushprajwal7 wants to merge 1 commit into
mkdocs:masterfrom
Manushprajwal7:fix/pathspec-dedent
Open

fix: dedent PathSpec config values before compiling patterns#4208
Manushprajwal7 wants to merge 1 commit into
mkdocs:masterfrom
Manushprajwal7:fix/pathspec-dedent

Conversation

@Manushprajwal7

Copy link
Copy Markdown

Summary

While working on #4207 I noticed CI's test job failing consistently on test_draft_docs_with_comments_from_user_guide (Python 3.10+) — and confirmed it also fails the same way on current master, unrelated to that PR. This fixes the actual root cause.

Root cause: draft_docs, exclude_docs, and not_in_nav are all backed by config_options.PathSpec, which compiles the value via pathspec.gitignore.GitIgnoreSpec.from_lines(lines=value.splitlines()). pathspec's newer major release (1.x) correctly stops implicitly stripping leading whitespace from each pattern line — per the real gitignore format, leading whitespace is significant unless escaped. mkdocs never dedented the value first, so a value written with common leading indentation on every line (natural for a multi-line string in mkdocs.yml, and exactly what the affected test does) silently matches nothing once pathspec stopped compensating for it. mkdocs only declares pathspec >=0.11.1 with no upper bound, so this breaks silently as soon as a newer pathspec gets resolved.

Verified directly against pathspec.gitignore.GitIgnoreSpec:

  • pathspec==0.11.1 (mkdocs' declared minimum): matches correctly with or without this fix, since it stripped leading whitespace itself.
  • pathspec==1.1.1 (current release): matching silently breaks without this fix, works correctly with it.

Changes

  • mkdocs/config/config_options.py: dedent the value in PathSpec.run_validation() before splitting it into lines, so behavior is consistent regardless of which pathspec version is installed — matching how a YAML | block scalar's common indentation is normally handled.
  • Added PathSpecTest in mkdocs/tests/config/config_options_tests.py covering both the indented and non-indented cases directly against the config option.

Test plan

  • test_draft_docs_with_comments_from_user_guide (the originally-failing test) now passes under pathspec==1.1.1
  • Full suite passes identically under both pathspec==0.11.1 and pathspec==1.1.1 (726-727 passed; only the 4 pre-existing Windows-symlink-privilege errors remain, unrelated and present on unmodified master too)
  • New PathSpecTest covers both the indented (regression) and plain (no change in behavior) cases
  • black/isort/ruff check on changed files — clean

The 'test' CI job on this PR has been failing consistently, but on
inspection the failure (test_draft_docs_with_comments_from_user_guide)
is a real, reproducible bug independent of this PR's actual change -
it also fails on current master. Root-caused and fixed it here since
it was blocking CI either way.

Root cause: newer pathspec releases (1.x, vs. the >=0.11.1 mkdocs
requires) stopped implicitly stripping leading whitespace from each
gitignore-style pattern line - correctly, per the gitignore format,
where leading whitespace is significant unless escaped. mkdocs' own
PathSpec config option (used by draft_docs, exclude_docs, not_in_nav)
never dedented its input, so a value written with common leading
indentation across all lines (as naturally happens with a multi-line
YAML block scalar, and as the test itself does) silently matched
nothing once pathspec stopped compensating for it.

Verified directly against pathspec.gitignore.GitIgnoreSpec:
  - pathspec==0.11.1 (matches mkdocs' declared minimum): matches fine
    with or without the fix, since it stripped leading whitespace itself.
  - pathspec==1.1.1 (current release, unconstrained by mkdocs' >=0.11.1):
    matching silently breaks without this fix, works correctly with it.

Fix: dedent the value in PathSpec.run_validation() before splitting
it into lines, so behavior no longer depends on which pathspec version
happens to be installed - matching how a YAML '|' block scalar's
common indentation is normally handled.

Added a focused regression test (PathSpecTest) alongside the existing
integration-level coverage in
BuildTests.test_draft_docs_with_comments_from_user_guide, which now
passes under pathspec 1.1.1.

Full local suite (both pathspec==0.11.1 and the latest 1.1.1): 726-728
passed, only the 4 pre-existing Windows-symlink-privilege errors
remain (unrelated, present on master too).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression caused by newer pathspec (1.x) no longer stripping leading whitespace in gitignore patterns, which made indented multi-line PathSpec config values (e.g. draft_docs, exclude_docs, not_in_nav) silently stop matching. It normalizes MkDocs’ behavior across pathspec versions by dedenting the config value before compiling patterns, and adds direct unit coverage for the PathSpec option.

Changes:

  • Dedent PathSpec string values before splitting into lines and compiling with pathspec.gitignore.GitIgnoreSpec.from_lines(...).
  • Add focused unit tests verifying both indented (regression) and non-indented inputs compile and match as expected.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
mkdocs/config/config_options.py Dedents PathSpec values before compiling patterns to avoid indentation breaking matches under pathspec 1.x.
mkdocs/tests/config/config_options_tests.py Adds PathSpecTest to ensure indented and non-indented pattern strings behave correctly.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@Manushprajwal7

Copy link
Copy Markdown
Author

The 2 remaining `pypy-3.9` failures (Ubuntu and Windows) are unrelated to this change — they fail at the dependency-install step, before any test code runs: `cryptography`'s Rust extension no longer builds on PyPy 3.9 (PyO3 dropped support for it), and `zstandard` fails to build on Windows because `distutils` was removed. Confirmed the same two jobs fail identically on current `master` (run 31243474392), so this is a pre-existing CI/toolchain issue independent of this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants