all2md.cli.config
Configuration file discovery and loading for all2md CLI.
This module handles automatic discovery of configuration files, loading configs from JSON or TOML format, and merging configurations with proper priority handling.
- all2md.cli.config.find_config_in_parents(start_dir: Path | None = None, stop_dir: Path | None = None) Path | None
Find configuration file by searching parent directories.
Walks up the directory tree from start_dir, checking each directory for configuration files in priority order: 1. .all2md.toml 2. .all2md.json 3. pyproject.toml (with [tool.all2md] section)
The walk stops after checking
stop_dir(inclusive) when given, otherwise it continues to the filesystem root. Returns the first configuration file found.- Parameters:
start_dir (Path, optional) – Starting directory for search, defaults to current working directory
stop_dir (Path, optional) – Highest directory to search (inclusive). When provided, the walk does not ascend past it. Used to keep project discovery from escaping above the user’s home directory into shared parents such as the drive root.
- Returns:
Path to first config file found, or None if not found
- Return type:
Path or None
Examples
>>> config_path = find_config_in_parents() >>> if config_path: ... print(f"Found config at: {config_path}")
- all2md.cli.config.discover_config_file() Path | None
Discover configuration file in standard locations.
Searches for configuration files in the following order:
Parent directory search (from cwd up to filesystem root):
.all2md.toml (highest priority)
.all2md.yaml
.all2md.yml
.all2md.json
pyproject.toml with [tool.all2md] section
User home directory:
.all2md.toml
.all2md.yaml
.all2md.yml
.all2md.json
Returns the first configuration file found.
- Returns:
Path to discovered config file, or None if not found
- Return type:
Path or None
Examples
>>> config_path = discover_config_file() >>> if config_path: ... print(f"Found config at: {config_path}")
- all2md.cli.config.load_config_file(config_path: Path | str) Dict[str, Any]
Load configuration from JSON, TOML, YAML, or pyproject.toml file.
Auto-detects format based on file extension and name: - .json files: Loaded as JSON - .toml files: Loaded as TOML - .yaml/.yml files: Loaded as YAML - pyproject.toml: Extracts [tool.all2md] section
- Parameters:
config_path (Path or str) – Path to the configuration file
- Returns:
Configuration dictionary loaded from file
- Return type:
dict
- Raises:
argparse.ArgumentTypeError – If the file cannot be read, parsed, or has invalid format
Examples
>>> config = load_config_file(".all2md.toml") >>> print(config.get("attachment_mode")) save
>>> config = load_config_file("pyproject.toml") >>> print(config.get("attachment_mode")) skip
- all2md.cli.config.merge_configs(base: Dict[str, Any], override: Dict[str, Any]) Dict[str, Any]
Merge two configuration dictionaries with deep merging.
The override dictionary takes precedence over base for conflicting keys. Nested dictionaries are merged recursively, not replaced entirely.
- Parameters:
base (dict) – Base configuration dictionary
override (dict) – Override configuration dictionary (higher priority)
- Returns:
Merged configuration dictionary
- Return type:
dict
Examples
>>> base = {'pdf': {'pages': [1, 2]}, 'attachment_mode': 'skip'} >>> override = {'pdf': {'detect_columns': True}, 'attachment_mode': 'save'} >>> merged = merge_configs(base, override) >>> print(merged) {'pdf': {'pages': [1, 2], 'detect_columns': True}, 'attachment_mode': 'save'}
- all2md.cli.config.load_config_with_priority(explicit_path: str | None = None, env_var_path: str | None = None) Dict[str, Any]
Load configuration with proper priority handling.
Priority order (highest to lowest): 1. Explicit config file path (–config flag) 2. Environment variable config path (ALL2MD_CONFIG) 3. Auto-discovered config file (.all2md.toml or .all2md.json in cwd or home)
- Parameters:
explicit_path (str, optional) – Explicit config file path from –config flag
env_var_path (str, optional) – Config file path from ALL2MD_CONFIG environment variable
- Returns:
Loaded configuration dictionary (empty dict if no config found)
- Return type:
dict
- Raises:
argparse.ArgumentTypeError – If a config file is specified but cannot be loaded
Examples
>>> # Load from explicit path >>> config = load_config_with_priority(explicit_path="my_config.toml")
>>> # Load with auto-discovery >>> config = load_config_with_priority()
- all2md.cli.config.get_config_search_paths() list[Path]
Get list of representative paths for configuration file search.
Returns a list showing the search pattern used during config discovery. Note that the actual search walks up from cwd to filesystem root, checking each directory for config files.
- Returns:
List of representative config file paths in search order
- Return type:
list[Path]
Examples
>>> paths = get_config_search_paths() >>> for path in paths: ... print(path) /current/working/dir/.all2md.toml /current/working/dir/.all2md.yaml /current/working/dir/.all2md.yml /current/working/dir/.all2md.json /current/working/dir/pyproject.toml (... continues up parent directories to root ...) ~/.all2md.toml ~/.all2md.yaml ~/.all2md.yml ~/.all2md.json
- all2md.cli.config.apply_config_to_parser(parser: ArgumentParser, section: str, *, explicit_path: str | None = None, no_config: bool = False) Dict[str, Any]
Apply a config-file section as argparse defaults for a subcommand.
Loads configuration with the standard priority chain (explicit
--configpath, thenALL2MD_CONFIG, then auto-discovery) and applies values from the[section]table as defaults onparser. Because they are applied as defaults, explicit CLI arguments still override them, and the config in turn overrides the parser’s hard-coded defaults.This is the bridge that lets standalone subcommands (
view,serve,diff) honor config files the same way the main converter command does. Subcommand parsers use plain argparse actions rather than the converter’s tracking actions, so applying values as defaults before parsing is the correct way to get “config < CLI” precedence.Config keys are matched against argument destination names (snake_case), so
--no-waitis configured asno_waitand--max-upload-sizeasmax_upload_size. Hyphens in keys are accepted and normalized to underscores. For flags whose dest differs from the flag spelling (e.g.--no-contextstoresshow_context), use the dest name. Keys that do not match an optional argument are logged as warnings and ignored.Only the named
[section]table is consulted; top-level keys (which the main converter uses) are deliberately ignored to avoid collisions such as a top-levelformat(input format) leaking into a subcommand’s--format.Intended usage (call after all add_argument calls, before the final parse):
pre_args, _ = parser.parse_known_args(args) apply_config_to_parser( parser, "view", explicit_path=pre_args.config, no_config=pre_args.no_config ) parsed = parser.parse_args(args)
- Parameters:
parser (argparse.ArgumentParser) – Parser to apply defaults to.
section (str) – Config section name to read (e.g.
"view","serve","diff").explicit_path (str, optional) – Explicit config path (typically from a
--configflag).no_config (bool) – If True, skip all config loading and return an empty dict.
- Returns:
Mapping of dest -> value that was applied (useful for testing).
- Return type:
dict