Last active
May 21, 2026 07:03
-
-
Save tobiashochguertel/0baa3a91e425f8881d4bc94258ff46cb to your computer and use it in GitHub Desktop.
Generate config file path variants with customizable discovery matrix (dot-prefix, extensions, subdirectories)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env -S uv run --script | |
| # /// script | |
| # requires-python = ">=3.12" | |
| # dependencies = [ | |
| # "typer>=0.15", | |
| # "pydantic>=2.0", | |
| # ] | |
| # /// | |
| """ | |
| path-discovery.py | |
| Utility to generate all possible file path variants for config discovery. | |
| Usage: | |
| ./path-discovery.py resource-catalog | |
| ./path-discovery.py resource-catalog --dot-prefixed false | |
| ./path-discovery.py resource-catalog --extensions yaml json | |
| ./path-discovery.py resource-catalog --directories "" config .config | |
| ./path-discovery.py resource-catalog --import | python3 # print import snippet | |
| """ | |
| from __future__ import annotations | |
| from pathlib import Path | |
| from typing import Annotated | |
| import typer | |
| from pydantic import BaseModel | |
| class DiscoveryConfig(BaseModel): | |
| """Configuration for file path discovery. | |
| Controls which filename variants are generated by discover_paths(). | |
| All fields have defaults — override only what you need. | |
| """ | |
| search_cwd: bool = True | |
| dot_prefixed: bool = True | |
| dot_directory: bool = True | |
| extensions: list[str] = ["yaml", "yml"] | |
| directories: list[str] = ["config"] | |
| def discover_paths(name: str, config: DiscoveryConfig | None = None) -> list[Path]: | |
| """Generate all possible file paths for a given config filename. | |
| Combines the name with every extension, dot-prefix, and directory | |
| variant defined in the config to produce a flat list of candidate paths. | |
| Args: | |
| name: Base filename without extension (e.g., "resource-catalog"). | |
| config: Optional overrides. Defaults to yaml/yml, dot-prefixed, | |
| and .config/ + cwd directories. | |
| Returns: | |
| List of Path objects, unique and in a predictable order. | |
| """ | |
| if config is None: | |
| config = DiscoveryConfig() | |
| seen: set[str] = set() | |
| paths: list[Path] = [] | |
| dirs: list[str] = list(config.directories) | |
| if config.search_cwd: | |
| dirs.insert(0, "") | |
| expanded_dirs: list[str] = [] | |
| for d in dirs: | |
| expanded_dirs.append(d) | |
| if d and config.dot_directory and not d.startswith("."): | |
| expanded_dirs.append(f".{d}") | |
| for ext in config.extensions: | |
| for directory in expanded_dirs: | |
| dir_prefix = f"{directory}/" if directory else "" | |
| candidates: list[str] = [f"{dir_prefix}{name}.{ext}"] | |
| if config.dot_prefixed and not directory: | |
| candidates.append(f".{name}.{ext}") | |
| for c in candidates: | |
| if c not in seen: | |
| seen.add(c) | |
| paths.append(Path(c)) | |
| return paths | |
| app = typer.Typer( | |
| name="path-discovery", | |
| help="Generate file-path variants for config discovery.", | |
| no_args_is_help=True, | |
| pretty_exceptions_enable=False, | |
| ) | |
| @app.command() | |
| def main( | |
| name: Annotated[str, typer.Argument(help="Base filename (e.g., resource-catalog)")], | |
| search_cwd: Annotated[bool | None, typer.Option("--search-cwd", help="Include current working directory")] = None, | |
| dot_prefixed: Annotated[bool | None, typer.Option("--dot-prefixed", help="Prefix filename with . in cwd")] = None, | |
| dot_directory: Annotated[bool | None, typer.Option("--dot-directory", help="Auto-prefix directories with .")] = None, | |
| extensions: Annotated[list[str] | None, typer.Option("--extension", "-e", help="File extensions to include")] = None, | |
| directories: Annotated[list[str] | None, typer.Option("--directory", "-d", help="Subdirectories to search (e.g., config)")] = None, | |
| ) -> None: | |
| """Print all path variants for a given filename.""" | |
| config_kwargs = {} | |
| if search_cwd is not None: | |
| config_kwargs["search_cwd"] = search_cwd | |
| if dot_prefixed is not None: | |
| config_kwargs["dot_prefixed"] = dot_prefixed | |
| if dot_directory is not None: | |
| config_kwargs["dot_directory"] = dot_directory | |
| if extensions is not None: | |
| config_kwargs["extensions"] = extensions | |
| if directories is not None: | |
| config_kwargs["directories"] = directories | |
| config = DiscoveryConfig(**config_kwargs) if config_kwargs else None | |
| paths = discover_paths(name, config) | |
| for p in paths: | |
| print(p) | |
| if __name__ == "__main__": | |
| app() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment