boost-skill-cli 1.0.32__tar.gz → 1.0.33__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/_version.py +2 -2
- boost_skill_cli-1.0.33/boost_cli/cliparse.py +31 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/pkg.py +13 -13
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_skill_cli.egg-info/SOURCES.txt +2 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/design-roadmap.html +2 -2
- boost_skill_cli-1.0.33/tests/unit/test_cliparse.py +43 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/.gitignore +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/LICENSE +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/Makefile +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/README.md +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/index.html +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/docs/roadmap.html +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/setup.cfg +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/style/README.md +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/style/boost.css +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/style/boost.js +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/style/demo.html +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/unit/test_version.py +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0,
|
|
21
|
+
__version__ = version = '1.0.33'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 33)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""A branded ArgumentParser.
|
|
2
|
+
|
|
3
|
+
Argparse's default failure output is a raw, unstyled ``usage:`` block with a
|
|
4
|
+
bare ``prog: error: …`` line — nothing like boost's branded top-level dispatch
|
|
5
|
+
(which routes through :func:`output.err` and offers a "did you mean"). This
|
|
6
|
+
subclass routes a parser's own errors through the same Aurora output layer, so
|
|
7
|
+
a wrong invocation looks as designed as a right one.
|
|
8
|
+
|
|
9
|
+
Adopt it via :func:`parser` in place of ``argparse.ArgumentParser``. Sub-parsers
|
|
10
|
+
created with ``add_subparsers()`` inherit this class automatically, so a single
|
|
11
|
+
top-level swap brands a command's whole tree.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
from .core import output as out
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BoostArgumentParser(argparse.ArgumentParser):
|
|
22
|
+
def error(self, message: str): # noqa: D401 - argparse hook
|
|
23
|
+
"""Print a branded error + dimmed usage, then exit 2 (argparse's code)."""
|
|
24
|
+
out.err(message)
|
|
25
|
+
sys.stderr.write(out.c(self.format_usage(), out.DIM))
|
|
26
|
+
self.exit(2)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def parser(*args, **kwargs) -> BoostArgumentParser:
|
|
30
|
+
"""Drop-in replacement for ``argparse.ArgumentParser(...)``."""
|
|
31
|
+
return BoostArgumentParser(*args, **kwargs)
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
reinstall, bundle, import, migrate, pin, unpin, snapshot, export."""
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import argparse
|
|
6
5
|
import io
|
|
7
6
|
import json
|
|
8
7
|
import os
|
|
@@ -15,6 +14,7 @@ from datetime import datetime, timezone
|
|
|
15
14
|
from pathlib import Path
|
|
16
15
|
from typing import Dict, List, Optional
|
|
17
16
|
|
|
17
|
+
from .. import cliparse
|
|
18
18
|
from ..core import (agents, catalog, gitutil, journal, lockfile, paths,
|
|
19
19
|
registry, store, util)
|
|
20
20
|
from ..core import output as out
|
|
@@ -83,7 +83,7 @@ def _boostfile_text(skills: Dict[str, dict], via: str = "boost bundle dump") ->
|
|
|
83
83
|
# ── install ──────────────────────────────────────────────────────────────
|
|
84
84
|
|
|
85
85
|
def cmd_install(argv: List[str]) -> int:
|
|
86
|
-
ap =
|
|
86
|
+
ap = cliparse.parser(prog="boost install",
|
|
87
87
|
description="Install a skill from a tap registry")
|
|
88
88
|
ap.add_argument("names", nargs="+", metavar="NAME",
|
|
89
89
|
help="skill name, optionally qualified as tap:skill")
|
|
@@ -155,7 +155,7 @@ def cmd_install(argv: List[str]) -> int:
|
|
|
155
155
|
# ── uninstall ────────────────────────────────────────────────────────────
|
|
156
156
|
|
|
157
157
|
def cmd_uninstall(argv: List[str]) -> int:
|
|
158
|
-
ap =
|
|
158
|
+
ap = cliparse.parser(
|
|
159
159
|
prog="boost uninstall",
|
|
160
160
|
description="Remove an installed skill, rule, workflow, or config")
|
|
161
161
|
ap.add_argument("names", nargs="+", metavar="NAME")
|
|
@@ -194,7 +194,7 @@ _PLAN_LABELS = [
|
|
|
194
194
|
|
|
195
195
|
|
|
196
196
|
def cmd_sync(argv: List[str]) -> int:
|
|
197
|
-
ap =
|
|
197
|
+
ap = cliparse.parser(
|
|
198
198
|
prog="boost sync",
|
|
199
199
|
description="Reconcile installed skills & symlinks against the lock file")
|
|
200
200
|
ap.add_argument("--diff", action="store_true",
|
|
@@ -257,7 +257,7 @@ def cmd_sync(argv: List[str]) -> int:
|
|
|
257
257
|
# ── update ───────────────────────────────────────────────────────────────
|
|
258
258
|
|
|
259
259
|
def cmd_update(argv: List[str]) -> int:
|
|
260
|
-
ap =
|
|
260
|
+
ap = cliparse.parser(prog="boost update",
|
|
261
261
|
description="Sync taps or update installed skills")
|
|
262
262
|
ap.add_argument("tap", nargs="?", metavar="TAP", help="refresh only this tap")
|
|
263
263
|
ap.add_argument("--taps-only", action="store_true",
|
|
@@ -317,7 +317,7 @@ def cmd_update(argv: List[str]) -> int:
|
|
|
317
317
|
# ── reinstall ────────────────────────────────────────────────────────────
|
|
318
318
|
|
|
319
319
|
def cmd_reinstall(argv: List[str]) -> int:
|
|
320
|
-
ap =
|
|
320
|
+
ap = cliparse.parser(prog="boost reinstall",
|
|
321
321
|
description="Reinstall a skill or all skills (force)")
|
|
322
322
|
ap.add_argument("names", nargs="*", metavar="NAME")
|
|
323
323
|
ap.add_argument("--all", action="store_true",
|
|
@@ -369,7 +369,7 @@ def cmd_reinstall(argv: List[str]) -> int:
|
|
|
369
369
|
# ── bundle ───────────────────────────────────────────────────────────────
|
|
370
370
|
|
|
371
371
|
def cmd_bundle(argv: List[str]) -> int:
|
|
372
|
-
ap =
|
|
372
|
+
ap = cliparse.parser(prog="boost bundle",
|
|
373
373
|
description="Export/install skill sets via a Boostfile")
|
|
374
374
|
ap.add_argument("action", choices=("dump", "install"))
|
|
375
375
|
ap.add_argument("file", nargs="?", metavar="FILE",
|
|
@@ -481,7 +481,7 @@ def _bundle_install(file: Optional[str]) -> int:
|
|
|
481
481
|
# ── import ───────────────────────────────────────────────────────────────
|
|
482
482
|
|
|
483
483
|
def cmd_import(argv: List[str]) -> int:
|
|
484
|
-
ap =
|
|
484
|
+
ap = cliparse.parser(
|
|
485
485
|
prog="boost import",
|
|
486
486
|
description="Import skills from a GitHub URL or local path")
|
|
487
487
|
ap.add_argument("source", metavar="URL_OR_PATH")
|
|
@@ -552,7 +552,7 @@ def _import_root(root: Path, name: Optional[str], do_all: bool,
|
|
|
552
552
|
# ── migrate ──────────────────────────────────────────────────────────────
|
|
553
553
|
|
|
554
554
|
def cmd_migrate(argv: List[str]) -> int:
|
|
555
|
-
ap =
|
|
555
|
+
ap = cliparse.parser(
|
|
556
556
|
prog="boost migrate",
|
|
557
557
|
description="Migrate skills between agents or from Skills CLI")
|
|
558
558
|
ap.add_argument("--from", dest="src", metavar="AGENT",
|
|
@@ -625,7 +625,7 @@ def cmd_migrate(argv: List[str]) -> int:
|
|
|
625
625
|
# ── pin / unpin ──────────────────────────────────────────────────────────
|
|
626
626
|
|
|
627
627
|
def cmd_pin(argv: List[str]) -> int:
|
|
628
|
-
ap =
|
|
628
|
+
ap = cliparse.parser(prog="boost pin",
|
|
629
629
|
description="Pin a skill to its current version")
|
|
630
630
|
ap.add_argument("name", metavar="NAME")
|
|
631
631
|
args = ap.parse_args(argv)
|
|
@@ -633,7 +633,7 @@ def cmd_pin(argv: List[str]) -> int:
|
|
|
633
633
|
|
|
634
634
|
|
|
635
635
|
def cmd_unpin(argv: List[str]) -> int:
|
|
636
|
-
ap =
|
|
636
|
+
ap = cliparse.parser(prog="boost unpin",
|
|
637
637
|
description="Allow a pinned skill to update again")
|
|
638
638
|
ap.add_argument("name", metavar="NAME")
|
|
639
639
|
args = ap.parse_args(argv)
|
|
@@ -663,7 +663,7 @@ def _set_pin(name: str, pinned: bool) -> int:
|
|
|
663
663
|
# ── snapshot ─────────────────────────────────────────────────────────────
|
|
664
664
|
|
|
665
665
|
def cmd_snapshot(argv: List[str]) -> int:
|
|
666
|
-
ap =
|
|
666
|
+
ap = cliparse.parser(prog="boost snapshot",
|
|
667
667
|
description="Save & restore whole skill environments")
|
|
668
668
|
ap.add_argument("action", choices=("save", "list", "restore"))
|
|
669
669
|
ap.add_argument("arg", nargs="?", metavar="LABEL|ID",
|
|
@@ -784,7 +784,7 @@ def _snapshot_restore(snap_id: str) -> int:
|
|
|
784
784
|
# ── export ───────────────────────────────────────────────────────────────
|
|
785
785
|
|
|
786
786
|
def cmd_export(argv: List[str]) -> int:
|
|
787
|
-
ap =
|
|
787
|
+
ap = cliparse.parser(
|
|
788
788
|
prog="boost export",
|
|
789
789
|
description="Package skills as shareable zip/tar archives")
|
|
790
790
|
ap.add_argument("names", nargs="*", metavar="NAME",
|
|
@@ -13,6 +13,7 @@ boost_cli/__init__.py
|
|
|
13
13
|
boost_cli/__main__.py
|
|
14
14
|
boost_cli/_version.py
|
|
15
15
|
boost_cli/cli.py
|
|
16
|
+
boost_cli/cliparse.py
|
|
16
17
|
boost_cli/errors.py
|
|
17
18
|
boost_cli/commands/__init__.py
|
|
18
19
|
boost_cli/commands/bmad.py
|
|
@@ -84,6 +85,7 @@ tests/unit/test_agents.py
|
|
|
84
85
|
tests/unit/test_ai.py
|
|
85
86
|
tests/unit/test_catalog.py
|
|
86
87
|
tests/unit/test_claude_settings.py
|
|
88
|
+
tests/unit/test_cliparse.py
|
|
87
89
|
tests/unit/test_config.py
|
|
88
90
|
tests/unit/test_dense.py
|
|
89
91
|
tests/unit/test_embed.py
|
|
@@ -436,11 +436,11 @@
|
|
|
436
436
|
</article>
|
|
437
437
|
|
|
438
438
|
<article class="ritem" data-track="commands" data-impact="med">
|
|
439
|
-
<div class="ritem-top"><span class="rid">BOOST-D25</span><span class="rstatus
|
|
439
|
+
<div class="ritem-top"><span class="rid">BOOST-D25</span><span class="rstatus progress">In progress</span></div>
|
|
440
440
|
<h4>Branded usage & error output</h4>
|
|
441
441
|
<p>Grading confirmed this hits <b>every command with a required argument</b> — <code>boost uninstall</code>, <code>boost snapshot</code> and more all dump raw, unstyled <code>argparse</code>: a multi-line usage block with a bare <code>error:</code>, nothing like the branded top-level dispatch (which already routes through <code>Error:</code> + a difflib "did you mean"). The durable fix is a shared <code>BoostArgumentParser</code> subclass whose <code>error()</code>/usage route through the Aurora output layer, adopted across the ~50 per-command parsers — a broad, test-first sweep, so logged rather than rushed.</p>
|
|
442
442
|
<div class="rmeta"><span class="m-cat">ux</span><span>Complexity L</span><span class="m-imp med">Impact Med</span><span class="m-wow">★★★☆☆</span></div>
|
|
443
|
-
<div class="rref"><code>
|
|
443
|
+
<div class="rref"><code>cliparse.py (BoostArgumentParser) · pkg.py done · 9 files to go</code></div>
|
|
444
444
|
</article>
|
|
445
445
|
|
|
446
446
|
</div>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Unit tests: boost_cli/cliparse.BoostArgumentParser — branded errors."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from boost_cli import cliparse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture(autouse=True)
|
|
10
|
+
def plain(monkeypatch):
|
|
11
|
+
monkeypatch.setenv("NO_COLOR", "1")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_parser_returns_boost_subclass():
|
|
15
|
+
p = cliparse.parser(prog="boost demo")
|
|
16
|
+
assert isinstance(p, cliparse.BoostArgumentParser)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_error_is_branded_and_exits_2(capsys):
|
|
20
|
+
p = cliparse.parser(prog="boost demo")
|
|
21
|
+
p.add_argument("name")
|
|
22
|
+
with pytest.raises(SystemExit) as exc:
|
|
23
|
+
p.parse_args([]) # missing required positional
|
|
24
|
+
assert exc.value.code == 2
|
|
25
|
+
err = capsys.readouterr().err
|
|
26
|
+
assert err.startswith("Error: ") # branded, not bare "usage:"
|
|
27
|
+
assert "the following arguments are required" in err
|
|
28
|
+
assert "usage: boost demo" in err # usage still shown, below
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_valid_args_do_not_error(capsys):
|
|
32
|
+
p = cliparse.parser(prog="boost demo")
|
|
33
|
+
p.add_argument("--flag", action="store_true")
|
|
34
|
+
ns = p.parse_args(["--flag"])
|
|
35
|
+
assert ns.flag is True
|
|
36
|
+
assert capsys.readouterr().err == ""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_subparsers_inherit_branding():
|
|
40
|
+
p = cliparse.parser(prog="boost demo")
|
|
41
|
+
sub = p.add_subparsers()
|
|
42
|
+
child = sub.add_parser("go")
|
|
43
|
+
assert isinstance(child, cliparse.BoostArgumentParser)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/boost_skill_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boost_skill_cli-1.0.32 → boost_skill_cli-1.0.33}/tests/functional/test_cli_configuration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|