tan-cli 0.7.0__py3-none-any.whl
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.
- tan/__init__.py +0 -0
- tan/__main__.py +120 -0
- tan/cli.py +939 -0
- tan/command_table.py +265 -0
- tan/commands/__init__.py +8 -0
- tan/commands/bootstrap_cmd.py +4856 -0
- tan/commands/bootstrap_patches.py +164 -0
- tan/commands/bootstrap_toolchain_fetch.py +155 -0
- tan/commands/bootstrap_toolchain_pin.py +36 -0
- tan/commands/build/__init__.py +1 -0
- tan/commands/build/configure_inputs.py +277 -0
- tan/commands/build/execute.py +1852 -0
- tan/commands/build/host_python.py +59 -0
- tan/commands/build/link_stale.py +78 -0
- tan/commands/build/manifest.py +428 -0
- tan/commands/build/materialise.py +81 -0
- tan/commands/build/token_substitution.py +381 -0
- tan/commands/build/toolchain.py +482 -0
- tan/commands/build/user_defines_wipe.py +115 -0
- tan/commands/build/workspace_patches.py +65 -0
- tan/commands/build_cmd.py +2236 -0
- tan/commands/build_output.py +331 -0
- tan/commands/clean_cmd.py +1183 -0
- tan/commands/completion_cmd.py +786 -0
- tan/commands/debug_config_cmd.py +2425 -0
- tan/commands/diff_cmd.py +940 -0
- tan/commands/doctor_cmd.py +4767 -0
- tan/commands/examples_cmd.py +644 -0
- tan/commands/explain_cmd.py +1319 -0
- tan/commands/faultdecode_cmd.py +931 -0
- tan/commands/flash_atoc_guard.py +240 -0
- tan/commands/flash_cmd.py +5731 -0
- tan/commands/flash_mram_guard.py +150 -0
- tan/commands/flash_ram.py +578 -0
- tan/commands/flash_raw.py +583 -0
- tan/commands/generate_cmd.py +1456 -0
- tan/commands/image_cmd.py +753 -0
- tan/commands/init_cmd.py +1740 -0
- tan/commands/inspect_cmd.py +377 -0
- tan/commands/kconfig_cmd.py +734 -0
- tan/commands/model_cmd.py +1514 -0
- tan/commands/model_device_cmd.py +351 -0
- tan/commands/model_device_live.py +234 -0
- tan/commands/model_host_cmd.py +430 -0
- tan/commands/model_zoo_cmd.py +363 -0
- tan/commands/monitor_actions.py +125 -0
- tan/commands/monitor_cmd.py +626 -0
- tan/commands/monitor_session.py +505 -0
- tan/commands/new_som_cmd.py +1522 -0
- tan/commands/pinmux_cmd.py +568 -0
- tan/commands/presets_cmd.py +1123 -0
- tan/commands/probe_cmd.py +421 -0
- tan/commands/reset_cmd.py +354 -0
- tan/commands/reset_confirm.py +168 -0
- tan/commands/run_cmd.py +637 -0
- tan/commands/scaffold_cmd.py +490 -0
- tan/commands/sdk_cmd.py +1723 -0
- tan/commands/size_cmd.py +1020 -0
- tan/commands/support_bundle_cmd.py +1073 -0
- tan/commands/trace_cmd.py +341 -0
- tan/commands/validate_cmd.py +2009 -0
- tan/commands/west_forward_cmd.py +736 -0
- tan/commands/workspace_patch_check.py +296 -0
- tan/core/__init__.py +1 -0
- tan/core/alp_conf_pregen.py +100 -0
- tan/core/artifact_provenance.py +240 -0
- tan/core/atoc_guard.py +276 -0
- tan/core/atoc_guard_messages.py +232 -0
- tan/core/atoc_replacement.py +118 -0
- tan/core/atomic_write.py +178 -0
- tan/core/board_context.py +351 -0
- tan/core/board_diagnostic.py +111 -0
- tan/core/board_files.py +221 -0
- tan/core/board_validator.py +542 -0
- tan/core/board_validator_compat.py +196 -0
- tan/core/board_validator_run.py +129 -0
- tan/core/board_validator_schema.py +186 -0
- tan/core/board_validator_skew.py +46 -0
- tan/core/board_yaml_edit.py +295 -0
- tan/core/board_yaml_pos.py +118 -0
- tan/core/bootstrap.py +2572 -0
- tan/core/build_plan.py +625 -0
- tan/core/consent.py +104 -0
- tan/core/console_filter.py +245 -0
- tan/core/debug_launch.py +1803 -0
- tan/core/devicetree_lint.py +168 -0
- tan/core/dir_removal.py +229 -0
- tan/core/doctor_git.py +172 -0
- tan/core/doctor_libraries.py +253 -0
- tan/core/doctor_render.py +185 -0
- tan/core/doctor_scope.py +66 -0
- tan/core/doctor_setools.py +237 -0
- tan/core/doctor_stale.py +180 -0
- tan/core/document_guards.py +723 -0
- tan/core/dp_id.py +97 -0
- tan/core/elf_load.py +63 -0
- tan/core/error_catalog.py +171 -0
- tan/core/example_catalog.py +499 -0
- tan/core/example_facets.py +151 -0
- tan/core/faultdecode.py +521 -0
- tan/core/flash_plan.py +2501 -0
- tan/core/flow_d_report.py +381 -0
- tan/core/flow_d_uptime.py +164 -0
- tan/core/fs_confine.py +130 -0
- tan/core/global_flags.py +230 -0
- tan/core/host_python.py +210 -0
- tan/core/image_bundle.py +247 -0
- tan/core/inert.py +147 -0
- tan/core/jlink_binary.py +128 -0
- tan/core/jlink_probe.py +481 -0
- tan/core/jsonc_splice.py +404 -0
- tan/core/launch_provenance.py +257 -0
- tan/core/link_refusal.py +76 -0
- tan/core/metadata_schema.py +376 -0
- tan/core/model_check.py +227 -0
- tan/core/model_device.py +449 -0
- tan/core/model_doctor.py +198 -0
- tan/core/model_host.py +48 -0
- tan/core/model_list.py +112 -0
- tan/core/model_zoo.py +353 -0
- tan/core/module_template.py +340 -0
- tan/core/mram_link.py +87 -0
- tan/core/new_som_ospi.py +94 -0
- tan/core/os_class.py +159 -0
- tan/core/patch_paths.py +87 -0
- tan/core/pending.py +40 -0
- tan/core/plain_zephyr_plan.py +138 -0
- tan/core/plan_exec.py +373 -0
- tan/core/plan_tokens.py +600 -0
- tan/core/probe.py +155 -0
- tan/core/probe_plan.py +237 -0
- tan/core/proxy.py +168 -0
- tan/core/publish.py +31 -0
- tan/core/python_floor.py +178 -0
- tan/core/ram_run.py +694 -0
- tan/core/ram_watch.py +231 -0
- tan/core/raw_write.py +160 -0
- tan/core/reset_plan.py +56 -0
- tan/core/run.py +161 -0
- tan/core/scaffold.py +2203 -0
- tan/core/scaffold_selftest_identity.py +225 -0
- tan/core/sdk_default_registry.py +565 -0
- tan/core/sdk_discovery.py +996 -0
- tan/core/sdk_removal.py +465 -0
- tan/core/serial_actions.py +175 -0
- tan/core/serial_capture.py +185 -0
- tan/core/serial_url.py +45 -0
- tan/core/setools.py +608 -0
- tan/core/setools_scratch.py +243 -0
- tan/core/shapes.py +194 -0
- tan/core/size.py +610 -0
- tan/core/som_buildability.py +204 -0
- tan/core/som_schema_version.py +62 -0
- tan/core/subprocess_env.py +201 -0
- tan/core/sysbuild_image.py +94 -0
- tan/core/system_manifest.py +827 -0
- tan/core/text_layout.py +73 -0
- tan/core/timestamp.py +182 -0
- tan/core/tool_lookup.py +383 -0
- tan/core/toolchain_pin.py +117 -0
- tan/core/toolchain_provision.py +1224 -0
- tan/core/trusted_path.py +134 -0
- tan/core/uboot_breakin.py +154 -0
- tan/core/uri_reference.py +415 -0
- tan/core/user_defines.py +152 -0
- tan/core/venv.py +332 -0
- tan/core/west_patches.py +143 -0
- tan/core/west_workspace_refusal.py +159 -0
- tan/core/zephyr_env.py +124 -0
- tan/env.py +185 -0
- tan/envelope.py +647 -0
- tan/exit_codes.py +12 -0
- tan/lazy_typer.py +185 -0
- tan/model/__init__.py +2 -0
- tan/model/_gen_fixture.py +132 -0
- tan/model/adapters/__init__.py +116 -0
- tan/model/adapters/cpu.py +26 -0
- tan/model/adapters/deepx.py +94 -0
- tan/model/adapters/drpai.py +242 -0
- tan/model/adapters/ethos_u.py +951 -0
- tan/model/adapters/executorch.py +55 -0
- tan/model/analyze.py +694 -0
- tan/model/build.py +304 -0
- tan/model/check.py +682 -0
- tan/model/manifest.py +625 -0
- tan/model/measure.py +216 -0
- tan/model/npu_ops_validate.py +130 -0
- tan/model/package.py +125 -0
- tan/model/perf.py +635 -0
- tan/model/perf_apply.py +721 -0
- tan/model/prep.py +193 -0
- tan/model/sram_fit.py +502 -0
- tan/model/targets.py +374 -0
- tan/model/tensorio.py +287 -0
- tan/net.py +73 -0
- tan/output_format.py +213 -0
- tan/planner/__init__.py +219 -0
- tan/planner/aperture.py +202 -0
- tan/planner/buildplan.py +1092 -0
- tan/planner/camera_owner.py +192 -0
- tan/planner/cameras.py +132 -0
- tan/planner/carveout.py +755 -0
- tan/planner/cli.py +274 -0
- tan/planner/headers.py +315 -0
- tan/planner/kconfig.py +2435 -0
- tan/planner/kconfig_symbols.py +473 -0
- tan/planner/libraries.py +677 -0
- tan/planner/link_target.py +237 -0
- tan/planner/linux_ownership.py +216 -0
- tan/planner/loader.py +1525 -0
- tan/planner/manifest.py +116 -0
- tan/planner/memory.py +161 -0
- tan/planner/memregion.py +56 -0
- tan/planner/models.py +533 -0
- tan/planner/orchestrator.py +874 -0
- tan/planner/ownership.py +203 -0
- tan/planner/partition.py +1160 -0
- tan/planner/paths.py +32 -0
- tan/planner/plain_slice.py +139 -0
- tan/planner/project_emit/__init__.py +60 -0
- tan/planner/project_emit/bom_netlist.py +375 -0
- tan/planner/project_emit/dts.py +580 -0
- tan/planner/project_emit/hw_info.py +221 -0
- tan/planner/project_emit/native_sim.py +136 -0
- tan/planner/project_emit/west_libs.py +213 -0
- tan/planner/project_loader.py +264 -0
- tan/planner/sdk_capability.py +203 -0
- tan/planner/sdk_compat.py +395 -0
- tan/planner/secure.py +350 -0
- tan/planner/slugs.py +394 -0
- tan/planner/som_metadata.py +325 -0
- tan/planner/strict_loaders.py +131 -0
- tan/planner/template.py +1037 -0
- tan/planner/template_pins.py +535 -0
- tan/planner/template_rewrite.py +714 -0
- tan/planner/topology.py +208 -0
- tan/planner/validate.py +365 -0
- tan/planner/whole_device_alias.py +67 -0
- tan/planner/zephyr_board.py +3510 -0
- tan/planner_cli.py +97 -0
- tan/planner_emit.py +617 -0
- tan/planner_root.py +119 -0
- tan/soc_ref.py +58 -0
- tan/templates/__init__.py +34 -0
- tan/templates/vendored/MANIFEST.md +1862 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/README.md +112 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/board.yaml +38 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.conf +11 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.overlay +29 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/prj.conf +5 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/src/main.c +266 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/testcase.yaml +53 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/README.md +112 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/board.yaml +38 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.conf +11 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.overlay +29 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/prj.conf +5 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/src/main.c +266 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/testcase.yaml +53 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/CMakeLists.txt +10 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/README.md +75 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/board.yaml +38 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/prj.conf +8 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.c +371 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.h +178 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/main.c +373 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/testcase.yaml +62 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/CMakeLists.txt +10 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/README.md +75 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/board.yaml +37 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/prj.conf +8 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.c +371 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.h +178 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/main.c +373 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/testcase.yaml +62 -0
- tan/templates/vendored/iot/E1M-AEN801/CMakeLists.txt +14 -0
- tan/templates/vendored/iot/E1M-AEN801/README.md +103 -0
- tan/templates/vendored/iot/E1M-AEN801/board.yaml +69 -0
- tan/templates/vendored/iot/E1M-AEN801/prj.conf +15 -0
- tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.c +196 -0
- tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.h +173 -0
- tan/templates/vendored/iot/E1M-AEN801/src/main.c +262 -0
- tan/templates/vendored/iot/E1M-AEN801/testcase.yaml +68 -0
- tan/templates/vendored/minimal/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/minimal/E1M-AEN801/README.md +108 -0
- tan/templates/vendored/minimal/E1M-AEN801/board.yaml +32 -0
- tan/templates/vendored/minimal/E1M-AEN801/prj.conf +8 -0
- tan/templates/vendored/minimal/E1M-AEN801/src/main.c +111 -0
- tan/templates/vendored/minimal/E1M-AEN801/testcase.yaml +49 -0
- tan/templates/vendored/minimal/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/minimal/E1M-V2N101/README.md +108 -0
- tan/templates/vendored/minimal/E1M-V2N101/board.yaml +32 -0
- tan/templates/vendored/minimal/E1M-V2N101/prj.conf +8 -0
- tan/templates/vendored/minimal/E1M-V2N101/src/main.c +111 -0
- tan/templates/vendored/minimal/E1M-V2N101/testcase.yaml +49 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/README.md +120 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/board.yaml +57 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/boards/native_sim_native_64.overlay +40 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/CMakeLists.txt +13 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/main.c +171 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/prj.conf +17 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/testcase.yaml +23 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/prj.conf +22 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/src/main.c +185 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/testcase.yaml +26 -0
- tan/templates/vendored/sensor/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/sensor/E1M-AEN801/README.md +112 -0
- tan/templates/vendored/sensor/E1M-AEN801/board.yaml +57 -0
- tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.conf +10 -0
- tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.overlay +28 -0
- tan/templates/vendored/sensor/E1M-AEN801/prj.conf +5 -0
- tan/templates/vendored/sensor/E1M-AEN801/src/main.c +186 -0
- tan/templates/vendored/sensor/E1M-AEN801/testcase.yaml +52 -0
- tan/templates/vendored/sensor/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/sensor/E1M-V2N101/README.md +112 -0
- tan/templates/vendored/sensor/E1M-V2N101/board.yaml +57 -0
- tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.conf +10 -0
- tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.overlay +28 -0
- tan/templates/vendored/sensor/E1M-V2N101/prj.conf +5 -0
- tan/templates/vendored/sensor/E1M-V2N101/src/main.c +186 -0
- tan/templates/vendored/sensor/E1M-V2N101/testcase.yaml +52 -0
- tan/version.py +102 -0
- tan_cli-0.7.0.dist-info/METADATA +125 -0
- tan_cli-0.7.0.dist-info/RECORD +330 -0
- tan_cli-0.7.0.dist-info/WHEEL +5 -0
- tan_cli-0.7.0.dist-info/entry_points.txt +2 -0
- tan_cli-0.7.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""`tan inspect` -- show resolved project/debug context values.
|
|
3
|
+
|
|
4
|
+
Port of `crates/tan-cli/src/commands/inspect.rs` + the `tan_core::debug`
|
|
5
|
+
model it reads (`crates/tan-core/src/debug/{context,inspect}.rs`). Builds the
|
|
6
|
+
same six-row "resolved debug context" -- `workspaceRoot`, `sdkRoot`,
|
|
7
|
+
`boardYamlPath`, `boardYamlExists`, `westCwd`, `pythonBinary` -- that `tan
|
|
8
|
+
trace`/`tan support-bundle` (#257) also need. [`resolve_debug_project_context`]
|
|
9
|
+
and [`collect_resolved_values`] below are this port's ONE copy of that model:
|
|
10
|
+
`trace_cmd.py` and `support_bundle_cmd.py` import both directly rather than
|
|
11
|
+
re-deriving them, mirroring how the Rust `tan_core::debug` module is the one
|
|
12
|
+
place all three commands read it from.
|
|
13
|
+
|
|
14
|
+
**Established by RUNNING the oracle (`target/debug/tan.exe`), not by reading
|
|
15
|
+
`crates/`** -- issues #258/#260/#261 all record source-reading alone producing
|
|
16
|
+
a wrong answer here twice already. Every shape below (the six rows, their
|
|
17
|
+
`source`/`detail` strings, the JSON key order, the mixed-separator `outputPath`
|
|
18
|
+
shape `trace`/`support-bundle` share) was measured against a freshly-built
|
|
19
|
+
oracle from THIS worktree's `crates/` (`cargo build -p alp-tan-cli --bin tan`),
|
|
20
|
+
not a possibly-stale `dev`-branch checkout's binary -- the two disagree on
|
|
21
|
+
`Project.boardYaml`'s existence-filtering (tan-cli#236, landed on this
|
|
22
|
+
worktree's branch, not yet on `dev`), which is exactly the kind of mismatch
|
|
23
|
+
RUNNING catches and reading `crates/` alone would not.
|
|
24
|
+
|
|
25
|
+
**Which SDK ladder.** `inspect`/`trace` are two of the thirteen commands
|
|
26
|
+
`tan.core.sdk_discovery.resolve_sdk_root_ladder`'s own docstring names -- measured against
|
|
27
|
+
the oracle -- as resolving the LATERAL/narrow ladder (the same one
|
|
28
|
+
`doctor_cmd.doctor` uses), not the wide `init`/`generate`/`examples`
|
|
29
|
+
one. This file calls `resolve_sdk_root_ladder` directly for that reason,
|
|
30
|
+
rather than `build_output.resolve_project_context`'s narrower
|
|
31
|
+
`resolve_sdk_tiered` (no positional-walk tail) that `size`/`image`/
|
|
32
|
+
`debug-config` use for their own, separately-documented reason.
|
|
33
|
+
|
|
34
|
+
**Always-populated fields.** No `--west-cwd`/`--python-path` flag exists on
|
|
35
|
+
this CLI surface at all (the oracle's own `GlobalArgs` carries neither), so
|
|
36
|
+
`westCwd` always equals the resolved `workspaceRoot` and `pythonBinary` is
|
|
37
|
+
always the per-platform default (`python` on Windows, `python3` elsewhere) --
|
|
38
|
+
verified against the oracle: every resolved-values row for these two keys
|
|
39
|
+
reports source `setting`/`default` respectively, in every argument shape
|
|
40
|
+
tried, never `unresolved`/`setting`-from-an-override. The Rust
|
|
41
|
+
`collect_resolved_values`'s "nothing resolved" branches for `workspaceRoot`/
|
|
42
|
+
`boardYamlPath`/`westCwd` are therefore dead code in THIS port's construction
|
|
43
|
+
(the workspace root and the joined board.yaml path are always non-null once a
|
|
44
|
+
command reaches this point) and are not reproduced here.
|
|
45
|
+
|
|
46
|
+
`tan inspect` itself has no failure exit in the oracle -- verified against
|
|
47
|
+
every argument shape tried (missing SDK, missing board.yaml, an empty
|
|
48
|
+
`--path`, `--path` matching nothing): always exit 0, with an `issues` entry
|
|
49
|
+
carrying the bad news instead.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from __future__ import annotations
|
|
53
|
+
|
|
54
|
+
import json
|
|
55
|
+
import os
|
|
56
|
+
from dataclasses import dataclass
|
|
57
|
+
from pathlib import Path
|
|
58
|
+
from typing import Any
|
|
59
|
+
|
|
60
|
+
import typer
|
|
61
|
+
|
|
62
|
+
from tan.commands.sdk_cmd import NO_SDK_NEXT_STEPS
|
|
63
|
+
from tan.core.sdk_discovery import _abs_posix, resolve_sdk_root_ladder, sdk_resolution_issues
|
|
64
|
+
from tan.core.timestamp import generated_at_iso
|
|
65
|
+
from tan.envelope import Envelope, Issue, Project, SdkInfo, emit
|
|
66
|
+
from tan.exit_codes import ExitCode
|
|
67
|
+
from tan.output_format import FORMAT_HELP, OutputFormat, resolve_format
|
|
68
|
+
|
|
69
|
+
#: `data.schemaVersion` for this command's payload.
|
|
70
|
+
DATA_SCHEMA_VERSION = "1"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True)
|
|
74
|
+
class ResolvedDebugContext:
|
|
75
|
+
"""The resolved project/debug context `inspect`/`trace`/`support-bundle`
|
|
76
|
+
all build from the same four CLI inputs (`--project`/`--board-yaml`/
|
|
77
|
+
`--sdk-root`, plus the always-resolved host defaults). Mirrors the shape
|
|
78
|
+
`tan_core::debug::DebugWorkspaceContext` carries, minus the two fields
|
|
79
|
+
that only mean something inside an IDE extension host
|
|
80
|
+
(`project_selected`/`debugger_extensions`) -- the standalone CLI has no
|
|
81
|
+
reader for either (see `doctor_cmd`'s own note on the same gap)."""
|
|
82
|
+
|
|
83
|
+
#: Posix, absolute -- always resolved (cwd, or `--project` joined onto it).
|
|
84
|
+
workspace_root: str
|
|
85
|
+
#: Posix, absolute, or `None` when no alp-sdk checkout resolved.
|
|
86
|
+
sdk_root: str | None
|
|
87
|
+
#: The `SdkSourceTier` string `resolve_sdk_root_ladder` answered with
|
|
88
|
+
#: (`"sdkRootFlag"`/`"projectPin"`/`"globalDefault"`/`"discovery"`/`"none"`).
|
|
89
|
+
sdk_tier: str
|
|
90
|
+
#: Posix, absolute -- the resolved location, joined onto `workspace_root`
|
|
91
|
+
#: unconditionally (mirrors `project.rs::resolve_board_yaml_path`): this is
|
|
92
|
+
#: WHERE a board.yaml would live, whether or not one is actually there.
|
|
93
|
+
board_yaml_path: str
|
|
94
|
+
#: Whether a real file sits at `board_yaml_path` (probed once, here).
|
|
95
|
+
board_yaml_exists: bool
|
|
96
|
+
#: Always equals `workspace_root` -- see the module docstring.
|
|
97
|
+
west_cwd: str
|
|
98
|
+
#: Always the per-platform default -- see the module docstring.
|
|
99
|
+
python_binary: str
|
|
100
|
+
#: The envelope `project` block (`board_yaml` present only when the file
|
|
101
|
+
#: really exists -- `Project.resolved` applies that filter).
|
|
102
|
+
project: Project
|
|
103
|
+
#: The envelope `sdk` block, or `None` when nothing resolved.
|
|
104
|
+
sdk: SdkInfo | None
|
|
105
|
+
#: tan-cli#478: the project `~/.alp/sdk-default` was written FOR, when the
|
|
106
|
+
#: SDK resolved through `globalDefault` and that project is not this one.
|
|
107
|
+
#: `resolve_sdk_root_ladder` has always answered with it; this context
|
|
108
|
+
#: dropped it, so `inspect`/`trace`/`support-bundle` reported
|
|
109
|
+
#: `sourceTier: "globalDefault"` pointing at ANOTHER project's checkout
|
|
110
|
+
#: with `ok: true` and `issues: []` -- the exact silence tan-cli#464 closed
|
|
111
|
+
#: for `doctor`/`generate`/`build`/`presets`/`examples` and no one else.
|
|
112
|
+
#: `None` when the pointer is this project's own, or was never consulted.
|
|
113
|
+
foreign_global_default_for: str | None = None
|
|
114
|
+
#: The unreadable/unresolvable `.alp/sdk-path` pin, same carry-through.
|
|
115
|
+
#: Paired with the field above because `sdk_resolution_issues` emits the
|
|
116
|
+
#: two together, in that order, and a caller holding one but not the other
|
|
117
|
+
#: can only re-open half the hole.
|
|
118
|
+
broken_project_pin: str | None = None
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def resolve_debug_project_context(
|
|
122
|
+
project_arg: str | None, board_yaml_arg: str | None, sdk_root_arg: str | None
|
|
123
|
+
) -> ResolvedDebugContext:
|
|
124
|
+
"""Resolve `--project`/`--board-yaml`/`--sdk-root` into the shared debug
|
|
125
|
+
context. Mirrors `doctor_cmd.doctor`'s own workspace-root/board-yaml/SDK
|
|
126
|
+
preprocessing (same ladder, same `--board-yaml` anchoring rule) rather than
|
|
127
|
+
`build_output.resolve_project_context`'s -- see the module docstring for why
|
|
128
|
+
these two commands take the narrow ladder specifically.
|
|
129
|
+
"""
|
|
130
|
+
cwd = Path.cwd()
|
|
131
|
+
workspace_root_path = (
|
|
132
|
+
cwd if project_arg is None else Path(os.path.join(str(cwd), project_arg))
|
|
133
|
+
)
|
|
134
|
+
workspace_root = _abs_posix(str(workspace_root_path))
|
|
135
|
+
|
|
136
|
+
configured = board_yaml_arg or "board.yaml"
|
|
137
|
+
if os.path.isabs(configured):
|
|
138
|
+
board_yaml_path = _abs_posix(configured)
|
|
139
|
+
else:
|
|
140
|
+
board_yaml_path = _abs_posix(os.path.join(str(workspace_root_path), configured))
|
|
141
|
+
board_yaml_exists = os.path.isfile(board_yaml_path)
|
|
142
|
+
|
|
143
|
+
sdk_resolution = resolve_sdk_root_ladder(sdk_root_arg, workspace_root_path)
|
|
144
|
+
resolved_sdk = sdk_resolution.path
|
|
145
|
+
sdk_tier = sdk_resolution.tier
|
|
146
|
+
sdk_root = _abs_posix(str(resolved_sdk)) if resolved_sdk is not None else None
|
|
147
|
+
sdk = SdkInfo.from_resolution(sdk_root, sdk_resolution) if sdk_root is not None else None
|
|
148
|
+
|
|
149
|
+
python_binary = "python" if os.name == "nt" else "python3"
|
|
150
|
+
|
|
151
|
+
return ResolvedDebugContext(
|
|
152
|
+
workspace_root=workspace_root,
|
|
153
|
+
sdk_root=sdk_root,
|
|
154
|
+
sdk_tier=sdk_tier,
|
|
155
|
+
board_yaml_path=board_yaml_path,
|
|
156
|
+
board_yaml_exists=board_yaml_exists,
|
|
157
|
+
west_cwd=workspace_root,
|
|
158
|
+
python_binary=python_binary,
|
|
159
|
+
project=Project.resolved(workspace_root, board_yaml_path),
|
|
160
|
+
sdk=sdk,
|
|
161
|
+
# tan-cli#478: carried, not recomputed. The ladder already answered
|
|
162
|
+
# with both; dropping them here is what left three commands silent
|
|
163
|
+
# about resolving another project's SDK.
|
|
164
|
+
foreign_global_default_for=sdk_resolution.foreign_global_default_for,
|
|
165
|
+
broken_project_pin=sdk_resolution.broken_project_pin,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def collect_resolved_values(context: ResolvedDebugContext) -> list[dict[str, Any]]:
|
|
170
|
+
"""The six resolved-value rows, in the oracle's fixed order. Port of
|
|
171
|
+
`tan_core::debug::inspect::collect_resolved_values`, narrowed to the
|
|
172
|
+
branches this port's [`ResolvedDebugContext`] can actually produce -- see
|
|
173
|
+
the module docstring's "Always-populated fields" note."""
|
|
174
|
+
return [
|
|
175
|
+
{
|
|
176
|
+
"key": "workspaceRoot",
|
|
177
|
+
"value": context.workspace_root,
|
|
178
|
+
"source": "workspace",
|
|
179
|
+
"detail": "Resolved project directory (cwd, or --project <dir>).",
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"key": "sdkRoot",
|
|
183
|
+
"value": context.sdk_root,
|
|
184
|
+
"source": "workspace" if context.sdk_root is not None else "unresolved",
|
|
185
|
+
"detail": (
|
|
186
|
+
"Resolved alp-sdk root used for scripts and schemas."
|
|
187
|
+
if context.sdk_root is not None
|
|
188
|
+
# tan-cli#381: named `tan sdk switch <path>`, which refuses in
|
|
189
|
+
# this build (`sdk_cmd._run_not_ported`) -- the #305 dead end,
|
|
190
|
+
# re-introduced by a port written after that fix landed. The
|
|
191
|
+
# unresolved arm is the only one a reader acts on, so it takes
|
|
192
|
+
# the shared NO_SDK_NEXT_STEPS instead of its own wording.
|
|
193
|
+
else f"Unresolved -- {NO_SDK_NEXT_STEPS}."
|
|
194
|
+
),
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"key": "boardYamlPath",
|
|
198
|
+
"value": context.board_yaml_path,
|
|
199
|
+
"source": "setting",
|
|
200
|
+
"detail": "Resolved board.yaml path (default location, or --board-yaml <path>).",
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"key": "boardYamlExists",
|
|
204
|
+
"value": context.board_yaml_exists,
|
|
205
|
+
"source": "runtime",
|
|
206
|
+
"detail": (
|
|
207
|
+
"board.yaml exists at the resolved path."
|
|
208
|
+
if context.board_yaml_exists
|
|
209
|
+
else "board.yaml is missing at the resolved path."
|
|
210
|
+
),
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"key": "westCwd",
|
|
214
|
+
"value": context.west_cwd,
|
|
215
|
+
"source": "setting",
|
|
216
|
+
"detail": "Working directory used for west commands.",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"key": "pythonBinary",
|
|
220
|
+
"value": context.python_binary,
|
|
221
|
+
"source": "default",
|
|
222
|
+
"detail": "Interpreter used for loader and validation scripts.",
|
|
223
|
+
},
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def filter_resolved_values(
|
|
228
|
+
values: list[dict[str, Any]], focus: str | None
|
|
229
|
+
) -> list[dict[str, Any]]:
|
|
230
|
+
"""`focus is None` passes everything through; otherwise keep a value whose
|
|
231
|
+
`key` equals `focus` or is nested under it (a `focus.` dotted or `focus[`
|
|
232
|
+
indexed prefix) -- mirrors `inspect.rs::filter_resolved_values`."""
|
|
233
|
+
if focus is None:
|
|
234
|
+
return values
|
|
235
|
+
dot = f"{focus}."
|
|
236
|
+
bracket = f"{focus}["
|
|
237
|
+
return [
|
|
238
|
+
v
|
|
239
|
+
for v in values
|
|
240
|
+
if v["key"] == focus or v["key"].startswith(dot) or v["key"].startswith(bracket)
|
|
241
|
+
]
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _format_value_text(value: Any) -> str:
|
|
245
|
+
"""Strings JSON-quoted, everything else its compact JSON form -- mirrors
|
|
246
|
+
Rust's `format_value` (`Value::String` -> `serde_json::to_string`, else
|
|
247
|
+
`Value::to_string()`).
|
|
248
|
+
|
|
249
|
+
`ensure_ascii=False`, for the same reason `diff_cmd._format_value` carries
|
|
250
|
+
it: `serde_json::to_string` emits raw UTF-8 and never a `\\uXXXX` escape, so
|
|
251
|
+
the default `ensure_ascii=True` printed `/home/<user>/jos\\u00e9-proj` where
|
|
252
|
+
the oracle prints `/home/<user>/josé-proj` -- a path that no longer equals
|
|
253
|
+
disk and can no longer be pasted back into a shell. Every OTHER scalar
|
|
254
|
+
(`true`/`false`/`null`/a bare number) renders identically either way, so
|
|
255
|
+
this is the only character class the two languages ever disagreed on.
|
|
256
|
+
"""
|
|
257
|
+
return json.dumps(value, ensure_ascii=False)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _inspect_text_lines(
|
|
261
|
+
values: list[dict[str, Any]], focus: str | None, show_origin: bool, quiet: bool
|
|
262
|
+
) -> list[str]:
|
|
263
|
+
lines = [f"inspect: resolved values={len(values)}"]
|
|
264
|
+
if focus is not None:
|
|
265
|
+
lines.append(f"path={focus}")
|
|
266
|
+
if not quiet:
|
|
267
|
+
for v in values:
|
|
268
|
+
rendered = _format_value_text(v["value"])
|
|
269
|
+
if show_origin:
|
|
270
|
+
lines.append(
|
|
271
|
+
f"{v['key']}={rendered} source={v['source']} "
|
|
272
|
+
f"detail={json.dumps(v['detail'], ensure_ascii=False)}"
|
|
273
|
+
)
|
|
274
|
+
else:
|
|
275
|
+
lines.append(f"{v['key']}={rendered}")
|
|
276
|
+
return lines
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def inspect(
|
|
280
|
+
ctx: typer.Context,
|
|
281
|
+
path: str = typer.Option(
|
|
282
|
+
None, "--path", metavar="PATH", help="Limit output to resolved values under this key path."
|
|
283
|
+
),
|
|
284
|
+
project: str = typer.Option(
|
|
285
|
+
None, "--project", metavar="PATH", help="Project root (defaults to current directory)."
|
|
286
|
+
),
|
|
287
|
+
board_yaml: str = typer.Option(
|
|
288
|
+
None,
|
|
289
|
+
"--board-yaml",
|
|
290
|
+
metavar="PATH",
|
|
291
|
+
help="Explicit board.yaml path (overrides project resolution).",
|
|
292
|
+
),
|
|
293
|
+
show_origin: bool = typer.Option(
|
|
294
|
+
False, "--show-origin", help="Include source + detail metadata for each value."
|
|
295
|
+
),
|
|
296
|
+
sdk_root: str = typer.Option(
|
|
297
|
+
None, "--sdk-root", metavar="PATH", help="alp-sdk checkout root."
|
|
298
|
+
),
|
|
299
|
+
output_format: OutputFormat = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
300
|
+
quiet: bool = typer.Option(False, "--quiet", help="Suppress non-essential output."),
|
|
301
|
+
verbose: bool = typer.Option(False, "--verbose", hidden=True),
|
|
302
|
+
no_color: bool = typer.Option(False, "--no-color", hidden=True),
|
|
303
|
+
non_interactive: bool = typer.Option(False, "--non-interactive", hidden=True),
|
|
304
|
+
ci: bool = typer.Option(False, "--ci", hidden=True),
|
|
305
|
+
target: str = typer.Option(None, "--target", hidden=True),
|
|
306
|
+
all_targets: bool = typer.Option(False, "--all", hidden=True),
|
|
307
|
+
) -> None:
|
|
308
|
+
"""Inspect resolved project/debug context values.
|
|
309
|
+
|
|
310
|
+
`--verbose`/`--no-color`/`--non-interactive`/`--ci`/`--target`/`--all` are
|
|
311
|
+
accepted and ignored: clap makes every one of them `global = true` in the
|
|
312
|
+
oracle, so `tan inspect --ci` (etc.) must not be a Click usage error even
|
|
313
|
+
though `inspect.rs` never reads any of them.
|
|
314
|
+
"""
|
|
315
|
+
del verbose, no_color, non_interactive, ci, target, all_targets
|
|
316
|
+
resolved_format = resolve_format(output_format, ctx.obj, choices=OutputFormat)
|
|
317
|
+
json_mode = resolved_format == "json"
|
|
318
|
+
|
|
319
|
+
generated_at = generated_at_iso(millis=True)
|
|
320
|
+
context = resolve_debug_project_context(project, board_yaml, sdk_root)
|
|
321
|
+
|
|
322
|
+
# tan-cli#478: FIRST, and unconditionally. `inspect`'s whole job is to say
|
|
323
|
+
# which SDK a build would use, so resolving another project's checkout
|
|
324
|
+
# through `globalDefault` is the single most load-bearing thing it can
|
|
325
|
+
# report -- and it reported the root while saying nothing about whose it
|
|
326
|
+
# was. Same helper, same order, as `size`/`image`/`flash`.
|
|
327
|
+
issues: list[Issue] = sdk_resolution_issues(
|
|
328
|
+
context.broken_project_pin, context.sdk_tier, context.foreign_global_default_for
|
|
329
|
+
)
|
|
330
|
+
if not context.board_yaml_exists:
|
|
331
|
+
issues.append(
|
|
332
|
+
Issue(
|
|
333
|
+
"inspect.board-yaml-missing",
|
|
334
|
+
"warning",
|
|
335
|
+
"board.yaml path could not be resolved or the file does not exist.",
|
|
336
|
+
)
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
focus = path
|
|
340
|
+
values = filter_resolved_values(collect_resolved_values(context), focus)
|
|
341
|
+
if focus is not None and not values:
|
|
342
|
+
issues.append(
|
|
343
|
+
Issue(
|
|
344
|
+
"inspect.path-not-found",
|
|
345
|
+
"warning",
|
|
346
|
+
f"No resolved values match --path '{focus}'.",
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
data = {
|
|
351
|
+
"schemaVersion": DATA_SCHEMA_VERSION,
|
|
352
|
+
"generatedAt": generated_at,
|
|
353
|
+
"focusPath": focus,
|
|
354
|
+
"showOrigin": show_origin,
|
|
355
|
+
"resolvedValues": values,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if not json_mode:
|
|
359
|
+
# tan-cli#478 review finding 6: `issues` has carried the
|
|
360
|
+
# foreign-default/broken-pin pair since the top of this function, but
|
|
361
|
+
# only the JSON branch below ever read it -- the DEFAULT text path
|
|
362
|
+
# stayed silent on the exact fact this command exists to disclose
|
|
363
|
+
# ("which SDK a build would use"). Printed first and unconditionally
|
|
364
|
+
# (unlike the `--quiet`-suppressed resolved-value lines).
|
|
365
|
+
for issue in issues:
|
|
366
|
+
if issue.code.startswith("sdk."):
|
|
367
|
+
typer.echo(issue.message, err=True)
|
|
368
|
+
for line in _inspect_text_lines(values, focus, show_origin, quiet):
|
|
369
|
+
typer.echo(line, err=True)
|
|
370
|
+
|
|
371
|
+
if json_mode:
|
|
372
|
+
emit(
|
|
373
|
+
Envelope(
|
|
374
|
+
"inspect", context.project, data, issues, ExitCode.SUCCESS, sdk=context.sdk
|
|
375
|
+
)
|
|
376
|
+
)
|
|
377
|
+
raise typer.Exit(int(ExitCode.SUCCESS))
|