Skip to content

feat: Centralized config output style system with --style flag#516

Open
tony wants to merge 5 commits into
masterfrom
output-styles
Open

feat: Centralized config output style system with --style flag#516
tony wants to merge 5 commits into
masterfrom
output-styles

Conversation

@tony

@tony tony commented Feb 15, 2026

Copy link
Copy Markdown
Member

Summary

  • Add a centralized config output style system with three named styles: concise (flask: "git+url"), standard (flask: {repo: "git+url"}), and verbose (flask: {repo: url, vcs: git, remotes: {...}})
  • Add --style CLI flag to fmt, add, discover, and import commands, with a settings.toml file for persistent defaults
  • Replace all hardcoded {"repo": url} entry creation across four command families with a single format_repo_entry() API

Three config styles

Style YAML example Python type
concise flask: "git+https://..." str
standard flask: {repo: "git+https://..."} dict (repo key only)
verbose flask: {repo: "git+url", vcs: "git", remotes: {origin: "..."}} dict (repo + vcs + remotes)

Default: standard (preserves current behavior — no breaking changes).

New files

File Purpose
src/vcspull/_internal/config_style.py format_repo_entry(), restyle_repo_entry(), apply_config_style() + helpers
src/vcspull/_internal/settings.py settings.toml loader with load_settings() / resolve_style()
tests/_internal/test_config_style.py 38 parametrized tests with syrupy snapshots
tests/_internal/test_settings.py 11 tests covering TOML parsing and style resolution

Key design decisions

  1. Output-only concernextract_repos() and validator.py already handle all three input forms; no changes needed there
  2. Lossy conversion warning — converting verbose→concise with extra keys (remotes, shell_command_after) emits a warning and preserves the entry unchanged
  3. Standard = current behavior — no existing functionality changes unless --style is explicitly passed or settings.toml is created
  4. CLI overrides settings--style flag beats settings.toml beats the built-in default

Commits (7 atomic)

  1. feat(types[ConfigStyle]) — enum + type alias
  2. feat(_internal[config_style]) — central formatting module + tests
  3. feat(_internal[settings]) — TOML settings + tomli dep + tests
  4. feat(cli/fmt[style])--style flag for bidirectional restyling
  5. feat(cli/add[style])format_repo_entry() with --style
  6. feat(cli/discover[style])format_repo_entry() with --style + cli dispatch
  7. feat(cli/import[style])format_repo_entry() with --style across 6 service handlers

Test plan

  • 1066 tests pass (51 new + 1015 existing)
  • uv run ruff check . clean
  • uv run ruff format --check . clean
  • uv run mypy clean (0 errors in 92 source files)
  • Manual: vcspull fmt --style concise --write converts dict entries to strings
  • Manual: vcspull fmt --style verbose --write converts string entries to dicts with remotes
  • Manual: vcspull add ./some-repo --style concise writes string entry
  • Manual: vcspull discover ~/code --style verbose --dry-run shows verbose entries
  • Manual: Create ~/.config/vcspull/settings.toml with config_style = "concise", verify default

@codecov

codecov Bot commented Feb 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.35032% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.36%. Comparing base (e6a62d9) to head (472746a).

Files with missing lines Patch % Lines
src/vcspull/_internal/config_style.py 80.61% 13 Missing and 6 partials ⚠️
src/vcspull/_internal/settings.py 95.34% 2 Missing ⚠️
src/vcspull/cli/fmt.py 80.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #516      +/-   ##
==========================================
+ Coverage   83.30%   83.36%   +0.06%     
==========================================
  Files          32       34       +2     
  Lines        4492     4647     +155     
  Branches      903      937      +34     
==========================================
+ Hits         3742     3874     +132     
- Misses        499      515      +16     
- Partials      251      258       +7     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Base automatically changed from scraper to master February 15, 2026 15:10
@tony tony force-pushed the output-styles branch 2 times, most recently from db913f7 to 0967b56 Compare February 16, 2026 01:32
@tony tony force-pushed the output-styles branch from 0967b56 to cf09c87 Compare July 5, 2026 14:51
@tony

tony commented Jul 5, 2026

Copy link
Copy Markdown
Member Author

Re-authored on current master. The three infrastructure commits (ConfigStyle/RawRepoEntry types, the central config_style formatter, and the settings loader with their tests) cherry-picked cleanly. The CLI wiring was rebuilt against master's current handlers rather than the stale versions the branch carried.

Landed: the flagship vcspull fmt --style {concise,standard,verbose}, threaded through format_config_file → format_single_config → format_config onto master's _classify_fmt_action flow (keeping save_config, not the branch's save_config_yaml). Restyling fires only on an explicit --style, so plain vcspull fmt is unchanged.

Deferred: styling newly-added entries in add/discover/import. Those handlers were each rebuilt around pinning (build_repo_entry, the _classify_* action enums, --prune-untracked) since this branch was authored, so wiring format_repo_entry into them is a separate, larger integration best done as a focused follow-up now that the ConfigStyle/config_style/settings infrastructure is in place. The full gate (ruff/mypy/pytest/build-docs) is green.

tony added 5 commits July 5, 2026 09:57
why: Centralize the three config output styles (concise, standard,
verbose) as a typed enum so all commands share the same vocabulary.
what:
- Add ConfigStyle enum with CONCISE, STANDARD, VERBOSE values
- Add RawRepoEntry TypeAlias (str | dict[str, Any])
why: All commands that write config entries (add, discover, import, fmt)
were independently hardcoding {"repo": url}. A central module enables
consistent output and bidirectional style conversion.
what:
- Add format_repo_entry() for creating new entries in any style
- Add restyle_repo_entry() for converting existing entries between styles
- Add apply_config_style() for bulk-transforming full config dicts
- Add helpers: _infer_vcs_from_url, _strip_vcs_prefix, _read_git_remotes,
  _extract_url, _has_extra_keys
- Lossy verbose→concise conversions warn and preserve original entry
- Add 38 parametrized tests with syrupy snapshots
why: Allow users to set a default config_style in settings.toml so they
don't need to pass --style on every command invocation.
what:
- Add settings.toml loader using tomllib (3.11+) with tomli fallback
- Add VcspullSettings dataclass with config_style field
- Add resolve_style() for CLI-flag-overrides-settings priority chain
- Add tomli>=1.0 conditional dependency for Python <3.11
- Add 11 tests covering TOML parsing, fallbacks, and resolution
why: fmt could only normalize toward the standard dict-with-repo-key
form. With the central config-style formatter now in place, fmt can
convert entries to concise (bare URL string) or verbose (full dict with
remotes) as well, letting users pick a house style for their config.

what:
- Add --style {concise,standard,verbose} to create_fmt_subparser
- Thread the style through format_config_file -> format_single_config ->
  format_config; the latter calls apply_config_style after sorting and
  surfaces lossy-conversion warnings
- Resolve the flag via settings.resolve_style at the CLI boundary,
  restyling only when --style is passed (keeps save_config, not
  save_config_yaml)
- Cover the conversion with a parametrized format_config test
why: The --style restyling and the ConfigStyle system are user-facing
additions for the next release and need a What's new entry.

what:
- Add a What's new entry describing vcspull fmt --style and the
  ConfigStyle output styles under the v1.66.x block
@tony tony force-pushed the output-styles branch from cf09c87 to 472746a Compare July 5, 2026 15:00
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.

1 participant