Skip to content

feat: Implement pretty-printing for Pydantic validation errors#182

Merged
sushant-suse merged 3 commits intoopenSUSE:mainfrom
sushant-suse:issue#158
Feb 18, 2026
Merged

feat: Implement pretty-printing for Pydantic validation errors#182
sushant-suse merged 3 commits intoopenSUSE:mainfrom
sushant-suse:issue#158

Conversation

@sushant-suse
Copy link
Copy Markdown
Collaborator

@sushant-suse sushant-suse commented Feb 17, 2026

Related Issue #158

Files Changed

  • src/docbuild/utils/errors.py:
    • Created a new utility format_pydantic_error.
    • Implements Smart Truncation: Shows the first 5 errors by default; use -vv to see the full list.
    • Implements Metadata Extraction: Dynamically retrieves Field titles and descriptions from the Pydantic models to show the user "what was expected".
    • Generates targeted links to documentation based on the error type (for example, extra_forbidden, bool_parsing).
  • src/docbuild/cli/cmd_cli.py:
    • Modified the AppConfig and EnvConfig validation blocks to catch ValidationError.
    • Routed those errors to the new formatter, passing the current verbosity level and filename.
    • Added safety checks to handle cases where config filenames might be None.
  • tests/utils/test_errors.py:
    • Added a new test suite to verify the formatter.
    • Ensures that nested field locations are resolved correctly.
    • Verified that truncation logic triggers correctly when multiple errors are present.
  • tests/cli/test_cmd_cli.py:
    • Updated existing CLI tests to verify the new error output format instead of the old logging behavior.

Verification Results

  • Verified that error paths are highlighted in yellow, error messages in red, and documentation links are clickable.
  • Confirmed that the "and X more errors" footer appears when the threshold is exceeded.
  • Passed ruff check and pytest.
  • Total project coverage reached 97.57% 🥳 (After the changes, it is 97.63%).

@sushant-suse sushant-suse requested a review from tomschr February 17, 2026 07:54
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 17, 2026

Coverage Report

For commit bc1085b

Click to expand Coverage Report
  Name                                           Stmts   Miss Branch BrPart  Cover
  --------------------------------------------------------------------------------
+ src/docbuild/cli/cmd_check/process.py             58      0     22      1  98.8%
+ src/docbuild/cli/cmd_cli.py                       93      1      8      1  98.0%
+ src/docbuild/utils/pidlock.py                     79      1     14      1  97.8%
+ src/docbuild/config/xml/stitch.py                 48      1     12      1  96.7%
+ src/docbuild/cli/cmd_validate/process.py         178      5     52      4  96.1%
+ src/docbuild/cli/callback.py                      35      0     10      2  95.6%
+ src/docbuild/cli/cmd_metadata/metaprocess.py     168     10     42      7  91.9%
- src/docbuild/cli/cmd_config/__init__.py            9      1      0      0  88.9%
- src/docbuild/cli/cmd_check/__init__.py            18      5      2      0  65.0%
- src/docbuild/cli/cmd_build/__init__.py            13      5      0      0  61.5%
- src/docbuild/cli/cmd_metadata/__init__.py         27     10      2      0  58.6%
- src/docbuild/cli/cmd_config/environment.py        11      6      2      0  38.5%
  --------------------------------------------------------------------------------
+ TOTAL                                           2790     45    642     17  98.0%
  
  48 files skipped due to complete coverage.

Copy link
Copy Markdown
Contributor

@tomschr tomschr left a comment

Choose a reason for hiding this comment

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

This is brilliant! 😍 It looks awesome!

One question in regards to output. For example, when the IP address is invalid, I get two errors:

(1) In 'server.host.function-plain[_validate()]':
    value is not a valid IPv4 or IPv6 address
    See: https://opensuse.github.io/docbuild/latest/errors/ip_any_address.html

(2) In 'server.host.constrained-str':
    String should match pattern '^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$'
    See: https://opensuse.github.io/docbuild/latest/errors/string_pattern_mismatch.html

This may be technically correct. I guess, we can't avoid that, right?

Comment thread src/docbuild/cli/cmd_cli.py Outdated
Comment thread src/docbuild/utils/errors.py Outdated
Comment thread src/docbuild/utils/errors.py Outdated
Comment thread src/docbuild/utils/errors.py
@sushant-suse
Copy link
Copy Markdown
Collaborator Author

This is brilliant! 😍 It looks awesome!

One question in regards to output. For example, when the IP address is invalid, I get two errors:

(1) In 'server.host.function-plain[_validate()]':
    value is not a valid IPv4 or IPv6 address
    See: https://opensuse.github.io/docbuild/latest/errors/ip_any_address.html

(2) In 'server.host.constrained-str':
    String should match pattern '^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$'
    See: https://opensuse.github.io/docbuild/latest/errors/string_pattern_mismatch.html

This may be technically correct. I guess, we can't avoid that, right?

That’s a great catch Toms! This happens because server.host is a Union type (IPvAnyAddress | DomainName). Pydantic attempts to validate against both, and since both fail, it reports both branches of the union.

You're right that we can't easily avoid the double error without complex custom validators, but I can definitely improve the 'In' location string. Right now, it's showing internal Pydantic noise like .function-plain and .constrained-str.

I have updated the formatter to 'clean' the path so it just shows server.host for both.

@sushant-suse sushant-suse requested a review from tomschr February 17, 2026 09:43
@tomschr
Copy link
Copy Markdown
Contributor

tomschr commented Feb 17, 2026

This may be technically correct. I guess, we can't avoid that, right?

That’s a great catch Toms! This happens because server.host is a Union type (IPvAnyAddress | DomainName). Pydantic attempts to validate against both, and since both fail, it reports both branches of the union.

Ahh, thanks for the explanation!

I don't think we can't really avoid it. I was just curious. 😃

Copy link
Copy Markdown
Contributor

@tomschr tomschr left a comment

Choose a reason for hiding this comment

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

That's a great progress! 👍 Apart from the minor suggestions below, I have only two final main points:

  • The coverage for cmd_cli.py is ~82%. Could you raise it to >90%?
  • IMHO, the Pydantic validation errors would be a great addition to docs/sources/user/config.rst, section Validationg the Configuration. You can remove the TODO then. 😉

Thank you so much!

Comment thread src/docbuild/cli/cmd_cli.py Outdated
Comment thread src/docbuild/cli/cmd_cli.py
Comment thread src/docbuild/cli/cmd_cli.py
Comment thread src/docbuild/cli/cmd_cli.py Outdated
Comment thread src/docbuild/cli/cmd_cli.py Outdated
@sushant-suse
Copy link
Copy Markdown
Collaborator Author

That's a great progress! 👍 Apart from the minor suggestions below, I have only two final main points:

  • The coverage for cmd_cli.py is ~82%. Could you raise it to >90%?
  • IMHO, the Pydantic validation errors would be a great addition to docs/sources/user/config.rst, section Validationg the Configuration. You can remove the TODO then. 😉

Thank you so much!

That's a great progress! 👍 Apart from the minor suggestions below, I have only two final main points:

  • The coverage for cmd_cli.py is ~82%. Could you raise it to >90%?
  • IMHO, the Pydantic validation errors would be a great addition to docs/sources/user/config.rst, section Validationg the Configuration. You can remove the TODO then. 😉

Thank you so much!

Hi @tomschr,

Thank you for the final suggestions! I have addressed both of your main points in the latest push:

  • I have increased the coverage for cmd_cli.py to 98.0%. I achieved this by adding tests to cover the help-trigger logic, non-Pydantic error handling, and locking exceptions. Total project coverage is now 98.1%.
  • I have updated docs/sources/user/config.rst to include a new section on 'Detailed Validation Feedback'. It explains the new error reporting features and includes a real-world example of the structured output. I also took the opportunity to add a 'Fixing Common Issues' subsection and removed the TODO as requested. 😉

The CI is green on macOS, and I’ve verified the formatting manually as well. Ready for your final look and approval!

Copy link
Copy Markdown
Contributor

@tomschr tomschr left a comment

Choose a reason for hiding this comment

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

That's brilliant! 😍 Great addition, thank you so much!

🚢 it!

@sushant-suse sushant-suse merged commit 150bfc4 into openSUSE:main Feb 18, 2026
9 checks passed
@sushant-suse sushant-suse deleted the issue#158 branch February 18, 2026 09:04
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