Skip to content

Conversation

@meek2100
Copy link

@meek2100 meek2100 commented Nov 4, 2025

This pull request introduces the --config <path> command-line option, allowing users to explicitly define the path to their TOML configuration file, overriding the default recursive search for .mdformat.toml.

This feature primarily supports integration with modern tooling like pre-commit hooks and centralized configuration management systems where config files may live outside the project root or in a custom directory.

Key Changes:

  1. New CLI Argument: Added --config (type Path) to src/mdformat/_cli.py.
  2. Config Logic: Implemented read_single_config_file in src/mdformat/_conf.py to support direct path loading. The run function logic prioritizes --config and correctly handles non-existent file paths by exiting with an error.
  3. Tests: Added a new test case (test_config_override_precedence) verifying that the explicit --config correctly overrides auto-detected .mdformat.toml settings.
  4. Documentation: Updated docs/users/configuration_file.md to document the new usage.
  5. Code Quality Fix: Corrected the InvalidPath exception class in src/mdformat/_cli.py to properly call super().__init__(path), resolving the flake8-bugbear (B042) warning.

@meek2100
Copy link
Author

@hukkin,
This should be ready to go and would be very helpful to have merged for one of my projects.

Copy link
Contributor

@KyleKing KyleKing left a comment

Choose a reason for hiding this comment

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

I added a few minor comments as an active in the mdformat community and to possibly help this PR along, but I'm not a maintainer, so take my feedback with a grain of salt!

Comment on lines 61 to 68
with open(conf_path, "rb") as f:
try:
toml_opts = tomllib.load(f)
except tomllib.TOMLDecodeError as e:
raise InvalidConfError(f"Invalid TOML syntax: {e}")

_validate_keys(toml_opts, conf_path)
_validate_values(toml_opts, conf_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this snippet could be extracted into a shared helper? The only difference is the error message (which includes the config_path in the former)

"""


def read_single_config_file(config_path: Path) -> tuple[Mapping, Path | None]:
Copy link
Contributor

@KyleKing KyleKing Jan 20, 2026

Choose a reason for hiding this comment

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

This function should be cached like read_toml_opts (not strictly necessary, see proposal to hoist outside of the for loop)

Comment on lines 67 to 71
except FileNotFoundError as e:
if config_override_path and str(config_override_path) == str(e.args[0]):
print_error(f"Configuration file not found at: {e.args[0]}")
return 1
raise
Copy link
Contributor

Choose a reason for hiding this comment

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

What about raising a custom ConfigFileNotFoundError or ConfigOverrideNotFoundError (instead of the more general FileNotFoundError) with the relevant metadata, then this conditional logic isn't necessary?

try:
toml_opts, toml_path = read_toml(path.parent if path else Path.cwd())
if config_override_path:
toml_opts, toml_path = read_single_config_file(config_override_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually on caching, the config override file can be read outside of the loop because the configuration file isn't relative to the file path. Maybe something like:

(toml_opts, toml_path): tuple[...?, Path] = None, None
if config_override_path:
    toml_opts, toml_path = read_single_config_file(config_override_path)
    for path in file_paths:
        ...

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