From b202834d960731b0362ceb946ad49991dee9fadc Mon Sep 17 00:00:00 2001 From: danmaps Date: Wed, 25 Feb 2026 09:10:15 -0800 Subject: [PATCH] cli: add --active map filter to layers/tables --- cli/arcgispro_cli/commands/query.py | 42 +++++++++++++++--- cli/tests/test_cli.py | 69 ++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/cli/arcgispro_cli/commands/query.py b/cli/arcgispro_cli/commands/query.py index 0686138..218bde5 100644 --- a/cli/arcgispro_cli/commands/query.py +++ b/cli/arcgispro_cli/commands/query.py @@ -139,9 +139,10 @@ def map_cmd(name, path, as_json): @click.command("layers") @click.option("--path", "-p", type=click.Path(exists=True), help="Path to search for .arcgispro folder") @click.option("--map", "-m", "map_name", help="Filter by map name") +@click.option("--active", "active_map", is_flag=True, help="Only layers in the active map") @click.option("--broken", is_flag=True, help="Show only broken layers") @click.option("--json", "as_json", is_flag=True, help="Output as JSON") -def layers_cmd(path, map_name, broken, as_json): +def layers_cmd(path, map_name, active_map, broken, as_json): """List all layers.""" import json as json_lib @@ -150,8 +151,21 @@ def layers_cmd(path, map_name, broken, as_json): layers = context.get("layers") or [] # Apply filters + if map_name and active_map: + console.print("[red]✗[/red] Use either --map or --active (not both)") + raise SystemExit(1) + + if active_map: + maps = context.get("maps") or [] + active = next((m for m in maps if m.get("isActiveMap")), maps[0] if maps else None) + if not active: + console.print("[yellow]No maps found[/yellow]") + return + map_name = active.get("name") + if map_name: - layers = [l for l in layers if l.get("mapName", "").lower() == map_name.lower()] + layers = [l for l in layers if l.get("mapName", "").lower() == str(map_name).lower()] + if broken: layers = [l for l in layers if l.get("isBroken")] @@ -351,19 +365,37 @@ def fields_cmd(layer_name, path, as_json): @click.command("tables") @click.option("--path", "-p", type=click.Path(exists=True), help="Path to search for .arcgispro folder") +@click.option("--map", "-m", "map_name", help="Filter by map name") +@click.option("--active", "active_map", is_flag=True, help="Only tables in the active map") @click.option("--json", "as_json", is_flag=True, help="Output as JSON") -def tables_cmd(path, as_json): +def tables_cmd(path, map_name, active_map, as_json): """List standalone tables.""" import json as json_lib arcgispro_path = require_context(path) context = load_context_files(arcgispro_path) tables = context.get("tables") or [] - + + # Apply filters + if map_name and active_map: + console.print("[red]✗[/red] Use either --map or --active (not both)") + raise SystemExit(1) + + if active_map: + maps = context.get("maps") or [] + active = next((m for m in maps if m.get("isActiveMap")), maps[0] if maps else None) + if not active: + console.print("[yellow]No maps found[/yellow]") + return + map_name = active.get("name") + + if map_name: + tables = [t for t in tables if t.get("mapName", "").lower() == str(map_name).lower()] + if as_json: console.print(json_lib.dumps(tables, indent=2)) return - + if not tables: console.print("[yellow]No standalone tables found[/yellow]") return diff --git a/cli/tests/test_cli.py b/cli/tests/test_cli.py index fefa83b..2edec85 100644 --- a/cli/tests/test_cli.py +++ b/cli/tests/test_cli.py @@ -51,7 +51,74 @@ def test_status_no_folder(): def test_addin_bundled(): """Test that the add-in file is bundled.""" from arcgispro_cli.commands.install import get_addin_path - + addin_path = get_addin_path() assert addin_path.exists(), f"Add-in not found at {addin_path}" assert addin_path.suffix == ".addin" + + +def _write_json(path, obj): + import json + + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(obj, indent=2), encoding="utf-8") + + +def test_layers_active_map_filter(): + runner = CliRunner() + with runner.isolated_filesystem(): + # minimal exported context + _write_json( + __import__("pathlib").Path(".arcgispro/context/maps.json"), + [ + {"name": "Map A", "isActiveMap": True}, + {"name": "Map B", "isActiveMap": False}, + ], + ) + _write_json( + __import__("pathlib").Path(".arcgispro/context/layers.json"), + [ + {"name": "L1", "mapName": "Map A", "isVisible": True}, + {"name": "L2", "mapName": "Map B", "isVisible": True}, + ], + ) + + result = runner.invoke(main, ["layers", "--active"]) + assert result.exit_code == 0 + assert "L1" in result.output + assert "L2" not in result.output + + +def test_tables_active_map_filter_json(): + runner = CliRunner() + with runner.isolated_filesystem(): + _write_json( + __import__("pathlib").Path(".arcgispro/context/maps.json"), + [ + {"name": "Map A", "isActiveMap": True}, + {"name": "Map B", "isActiveMap": False}, + ], + ) + _write_json( + __import__("pathlib").Path(".arcgispro/context/tables.json"), + [ + {"name": "T1", "mapName": "Map A"}, + {"name": "T2", "mapName": "Map B"}, + ], + ) + + result = runner.invoke(main, ["tables", "--active", "--json"]) + assert result.exit_code == 0 + assert "T1" in result.output + assert "T2" not in result.output + + +def test_layers_active_map_conflicts_with_map(): + runner = CliRunner() + with runner.isolated_filesystem(): + _write_json(__import__("pathlib").Path(".arcgispro/context/maps.json"), [{"name": "Map A", "isActiveMap": True}]) + _write_json(__import__("pathlib").Path(".arcgispro/context/layers.json"), []) + + result = runner.invoke(main, ["layers", "--active", "--map", "Map A"]) + assert result.exit_code == 1 + assert "either --map or --active" in result.output