From 436a4fcf6a01d0b3378a9ca87b8b48dfa42c3f8b Mon Sep 17 00:00:00 2001 From: Filipe Cavalcanti Date: Wed, 18 Feb 2026 10:32:28 -0300 Subject: [PATCH] feature: show defconfig content Adds `get_defconfig` method to Board class and CLI command to get the content of a defconfig, allowing a quick read without having to navigate the source code. Signed-off-by: Filipe Cavalcanti --- ntxbuild/cli.py | 15 +++++++++-- ntxbuild/nuttx.py | 7 +++++ tests/test_cli.py | 63 +++++++++++++++++++++++++++++++++++++++++++++ tests/test_nuttx.py | 28 ++++++++++++++++++++ 4 files changed, 111 insertions(+), 2 deletions(-) diff --git a/ntxbuild/cli.py b/ntxbuild/cli.py index aa320f7..c468ee9 100644 --- a/ntxbuild/cli.py +++ b/ntxbuild/cli.py @@ -556,9 +556,10 @@ def boards(soc, nuttx_dir, apps_dir): @list.command() @click.argument("board") +@click.option("--read", "-r", help="Read defconfig content", nargs=1) @click.option("--nuttx-dir", help="NuttX directory", default=NUTTX_DEFAULT_DIR_NAME) @click.option("--apps-dir", help="Apps directory", default=NUTTX_APPS_DEFAULT_DIR_NAME) -def defconfigs(board, nuttx_dir, apps_dir): +def defconfigs(board, read, nuttx_dir, apps_dir): """List available defconfigs for a specific board. Example usage: @@ -578,7 +579,17 @@ def defconfigs(board, nuttx_dir, apps_dir): if not boards_list: click.echo(f"Board not found: {board}") sys.exit(0) - boards_list[0].print_defconfig_summary() + board = boards_list[0] + if read: + defconfig = board.get_defconfig(read) + if defconfig: + click.echo(f"Defconfig content for {read}:") + click.echo(defconfig.content) + else: + click.echo(f"Defconfig not found: {read}") + sys.exit(1) + else: + board.print_defconfig_summary() sys.exit(0) except Exception as e: click.echo(f"❌ {e}") diff --git a/ntxbuild/nuttx.py b/ntxbuild/nuttx.py index 1233ec9..47625ee 100644 --- a/ntxbuild/nuttx.py +++ b/ntxbuild/nuttx.py @@ -117,6 +117,13 @@ def print_defconfig_summary(self): ) ) + def get_defconfig(self, name: str): + """Iterate available defconfigs and return the one with the given name.""" + for defconfig in self.defconfigs: + if defconfig.name == name: + return defconfig + return None + class NuttxBoardExplorer: """Helper to search for boards inside a NuttX repository. diff --git a/tests/test_cli.py b/tests/test_cli.py index 9697831..66e1364 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -646,3 +646,66 @@ def test_main_log_level_case_insensitive(self, nuttxspace_path): result = runner.invoke(main, ["--log-level", "debug", "start", "sim", "nsh"]) assert result.exit_code == 0 + + +class TestListDefconfigs: + """Test suite for the list defconfigs command.""" + + def test_list_defconfigs_without_read(self, nuttxspace_path): + """Test list defconfigs command without --read option.""" + os.chdir(nuttxspace_path) + + runner = CliRunner() + result = runner.invoke(main, ["list", "defconfigs", "sim"]) + + assert result.exit_code == 0 + # Should show defconfig summary + assert "Defconfigs" in result.output or "Total" in result.output + + def test_list_defconfigs_with_read_existing(self, nuttxspace_path): + """Test list defconfigs command with --read option for existing defconfig.""" + os.chdir(nuttxspace_path) + + runner = CliRunner() + result = runner.invoke(main, ["list", "defconfigs", "sim", "--read", "nsh"]) + + assert result.exit_code == 0 + assert "Defconfig content for nsh:" in result.output + # Should contain actual defconfig content (at least some CONFIG lines) + assert "CONFIG" in result.output or len(result.output) > 50 + + def test_list_defconfigs_with_read_short_option(self, nuttxspace_path): + """Test list defconfigs command with -r short option.""" + os.chdir(nuttxspace_path) + + runner = CliRunner() + result = runner.invoke(main, ["list", "defconfigs", "sim", "-r", "nsh"]) + + assert result.exit_code == 0 + assert "Defconfig content for nsh:" in result.output + + def test_list_defconfigs_with_read_nonexistent(self, nuttxspace_path): + """Test list defconfigs command with --read option for non-existent + defconfig. + """ + os.chdir(nuttxspace_path) + + runner = CliRunner() + result = runner.invoke( + main, ["list", "defconfigs", "sim", "--read", "nonexistent_defconfig_xyz"] + ) + + assert result.exit_code == 1 + assert "Defconfig not found: nonexistent_defconfig_xyz" in result.output + + def test_list_defconfigs_invalid_board(self, nuttxspace_path): + """Test list defconfigs command with invalid board name.""" + os.chdir(nuttxspace_path) + + runner = CliRunner() + result = runner.invoke( + main, ["list", "defconfigs", "nonexistent_board_xyz", "--read", "nsh"] + ) + + assert result.exit_code == 0 + assert "Board not found: nonexistent_board_xyz" in result.output diff --git a/tests/test_nuttx.py b/tests/test_nuttx.py index d532262..1cd8130 100644 --- a/tests/test_nuttx.py +++ b/tests/test_nuttx.py @@ -83,3 +83,31 @@ def test_nuttx_board_filter_setters_and_search(nuttxspace_path: Path): boards_board = nbf.set_board(board_name).boards # There should be at least one board matching the exact board name assert any(b.name == board_name for b in boards_board) + + +def test_board_get_defconfig(nuttxspace_path: Path): + """Test Board.get_defconfig method to retrieve defconfig by name.""" + nuttx_repo = nuttxspace_path / "nuttx" + if not nuttx_repo.exists(): + pytest.skip("nuttx repo not available in tests/nuttxspace") + + defconfig_file = _find_some_defconfig(nuttx_repo) + if not defconfig_file: + pytest.skip("No defconfig files found in nuttx repo; skipping test") + + defconfig_dir = defconfig_file.parent + board_path = defconfig_dir.parent.parent + board = Board(path=board_path) + + # Test getting an existing defconfig + defconfig_name = defconfig_dir.stem + found_defconfig = board.get_defconfig(defconfig_name) + assert found_defconfig is not None + assert found_defconfig.name == defconfig_name + assert found_defconfig.path == defconfig_dir + assert found_defconfig.content is not None + assert len(found_defconfig.content) > 0 + + # Test getting a non-existent defconfig + non_existent = board.get_defconfig("nonexistent_defconfig_xyz") + assert non_existent is None