Skip to content

Commit

Permalink
Add inspect command replacing list --output-format json (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
zanieb authored Jan 3, 2024
1 parent 506e6d2 commit c9874f7
Show file tree
Hide file tree
Showing 9 changed files with 670 additions and 106 deletions.
43 changes: 37 additions & 6 deletions src/packse/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
UserError,
)
from packse.index import index_down, index_up
from packse.inspect import inspect
from packse.list import list
from packse.publish import publish
from packse.serve import serve
Expand Down Expand Up @@ -126,10 +127,26 @@ def _call_list(args):
args.no_versions,
skip_invalid,
args.no_sources,
args.output_format,
)


def _call_inspect(args):
skip_invalid = args.skip_invalid
if not args.targets:
skip_invalid = True
targets = Path.cwd().glob("**/*.json")
else:
targets = []
for target in args.targets:
# Expand any directories to json files within
if target.is_dir():
targets.extend(target.glob("**/*.json"))
else:
targets.append(target)

inspect(targets, skip_invalid)


def _root_parser():
parser = argparse.ArgumentParser(
description="Utilities for working example packaging scenarios",
Expand Down Expand Up @@ -295,7 +312,7 @@ def _add_index_parser(subparsers):


def _add_list_parser(subparsers):
parser = subparsers.add_parser("list", help="List scenarios")
parser = subparsers.add_parser("list", help="List scenarios at the given paths")
parser.set_defaults(call=_call_list)
parser.add_argument(
"targets",
Expand All @@ -318,11 +335,24 @@ def _add_list_parser(subparsers):
action="store_true",
help="Do not show the source file for each scenario.",
)
_add_shared_arguments(parser)


def _add_inspect_parser(subparsers):
parser = subparsers.add_parser(
"inspect", help="Inspect scenarios at the given paths"
)
parser.set_defaults(call=_call_inspect)
parser.add_argument(
"targets",
type=Path,
nargs="*",
help="The scenario files to load",
)
parser.add_argument(
"--output-format",
choices=["pretty", "json"],
default="pretty",
help="The output format.",
"--skip-invalid",
action="store_true",
help="Skip invalid scenario files instead of failing.",
)
_add_shared_arguments(parser)

Expand Down Expand Up @@ -350,6 +380,7 @@ def get_parser() -> argparse.ArgumentParser:
_add_view_parser(subparsers)
_add_publish_parser(subparsers)
_add_list_parser(subparsers)
_add_inspect_parser(subparsers)
_add_serve_parser(subparsers)
_add_index_parser(subparsers)

Expand Down
47 changes: 47 additions & 0 deletions src/packse/inspect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""
Get details for all scenarios.
"""
import json
import logging
from pathlib import Path
from typing import cast

from packse.error import FileNotFound, InvalidScenario
from packse.scenario import (
Scenario,
load_scenarios,
scenario_prefix,
)
from packse.view import dependency_tree

logger = logging.getLogger(__name__)


def inspect(targets: list[Path], skip_invalid: bool = False):
scenarios_by_path: dict[Path, list[Scenario]] = {}

# Validate and collect all targets first
for target in sorted(targets):
if not target.exists():
raise FileNotFound(target)

try:
logger.debug("Loading %s", target)
scenarios_by_path[target] = load_scenarios(target)
except Exception as exc:
if not skip_invalid:
raise InvalidScenario(target, reason=str(exc)) from exc

# Collect a JSON-compatible representation for each scenario
result = {"scenarios": []}
for source, scenarios in scenarios_by_path.items():
for scenario in scenarios:
scenario = cast(Scenario, scenario)

raw = scenario.dict()
raw["source"] = str(source)
raw["prefix"] = scenario_prefix(scenario)
raw["tree"] = dependency_tree(scenario)
result["scenarios"].append(raw)

print(json.dumps(result, indent=2))
18 changes: 3 additions & 15 deletions src/packse/list.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""
List all scenarios.
"""
import json
import logging
from pathlib import Path
from typing import Literal, cast
from typing import cast

from packse.error import FileNotFound, InvalidScenario
from packse.scenario import (
Expand All @@ -21,7 +20,6 @@ def list(
no_versions: bool = False,
skip_invalid: bool = False,
no_sources: bool = False,
format: Literal["json", "pretty"] = "pretty",
):
scenarios_by_path: dict[Path, list[Scenario]] = {}

Expand All @@ -38,30 +36,20 @@ def list(
raise InvalidScenario(target, reason=str(exc)) from exc

# Then list each one
result = {"scenarios": []}
for source, scenarios in scenarios_by_path.items():
prefix = "" if no_sources else " " * 4
if not no_sources and format == "pretty":
if not no_sources:
print(to_display_path(source))

for scenario in scenarios:
scenario = cast(Scenario, scenario)

raw = scenario.dict()
raw["source"] = str(source)
raw["prefix"] = scenario_prefix(scenario)
result["scenarios"].append(raw)

if no_versions:
name = scenario.name
else:
name = scenario_prefix(scenario)

if format == "pretty":
print(prefix + name)

if format == "json":
print(json.dumps(result, indent=2))
print(prefix + name)


def to_display_path(path: Path | str, relative_to: Path | str | None = None) -> str:
Expand Down
2 changes: 1 addition & 1 deletion src/packse/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def view_scenario(scenario: Scenario):
print(dependency_tree(scenario))


def dependency_tree(scenario: Scenario):
def dependency_tree(scenario: Scenario) -> str:
"""
Generate a dependency tree for a scenario
"""
Expand Down
Loading

0 comments on commit c9874f7

Please sign in to comment.