From ab32fe20888f81de2808b4a92617d4c632fc99b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CB=B6=F0=9D=9E=A2=E2=A4=AC=E2=AB=92=E2=B5=96s=E1=90=BC?= =?UTF-8?q?=CB=B6?= <91800957+exdysa@users.noreply.github.com> Date: Sun, 12 Apr 2026 08:07:29 -0400 Subject: [PATCH] patch command and main --- negate/__main__.py | 12 ++- negate/command.py | 1 + .../results_real_20260412_080531.json | 3 + tests/test_main_help.py | 77 +++++++++++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 results/20260412_080531/results_real_20260412_080531.json create mode 100644 tests/test_main_help.py diff --git a/negate/__main__.py b/negate/__main__.py index 1721b9b..5a3bf06 100644 --- a/negate/__main__.py +++ b/negate/__main__.py @@ -14,6 +14,8 @@ from typing import Any from negate.io.console import CLI_LOGGER, set_root_folder +from negate.io.blurb import BlurbText +from negate.extract.unified_core import ExtractionModule ROOT_FOLDER = Path(__file__).resolve().parent.parent CONFIG_PATH = ROOT_FOLDER / "config" @@ -106,7 +108,9 @@ def _load_model_choices() -> ModelChoices: return choices -def _build_parser(blurb: BlurbText, choices: ModelChoices, list_results: list[str], list_model: list[str], inference_pair: list[str]) -> argparse.ArgumentParser: +def _build_parser( + blurb: BlurbText, choices: ModelChoices, list_results: list[str], list_model: list[str], inference_pair: list[str] +) -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Negate CLI") subparsers = parser.add_subparsers(dest="cmd", required=True) @@ -115,11 +119,13 @@ def _build_parser(blurb: BlurbText, choices: ModelChoices, list_results: list[st train_parser.add_argument("-l", "--loop", action="store_true", help=blurb.loop) train_parser.add_argument("-f", "--features", choices=list_results, default=None, help=blurb.features_load) - process_parser = subparsers.add_parser("process", help="Run all decompose/extract module combinations") + module_list = ", ".join(mod.name for mod in ExtractionModule) + process_help = f"Run all decompose/extract module combinations. Available modules: {module_list}" + process_parser = subparsers.add_parser("process", help=process_help) process_parser.add_argument("path", help=blurb.unidentified_path) process_parser.add_argument("-v", "--verbose", action="store_true", help=blurb.verbose) process_parser.add_argument("--transposed", default=None, help="Comma-separated transposed indices") - process_parser.add_argument("--combination", default=None, help="Comma-separated module names") + process_parser.add_argument("--combination", default=None, help=f"Comma-separated module names from: {module_list}") process_parser.add_argument("--train", choices=["convnext", "xgboost"], default=None, help="Train model after processing") vit_help = f"Vison {blurb.model_desc} {choices.default_vit}".strip() diff --git a/negate/command.py b/negate/command.py index ff53286..ca0c6cf 100644 --- a/negate/command.py +++ b/negate/command.py @@ -8,6 +8,7 @@ from pathlib import Path from typing import Any import time as timer_module +from negate.io.console import configure_runtime_logging, CLI_LOGGER start_ns = timer_module.perf_counter() diff --git a/results/20260412_080531/results_real_20260412_080531.json b/results/20260412_080531/results_real_20260412_080531.json new file mode 100644 index 0000000..cec4f95 --- /dev/null +++ b/results/20260412_080531/results_real_20260412_080531.json @@ -0,0 +1,3 @@ +{ + "x_p": "{'image_mean_ff': 0.5551752934617227, 'image_std': 0.0977445244532872, 'image_mean': (28894107043657, 57788214087314), 'diff_mean': (25353770906193, 50707541812387), 'laplace_mean': (24083985868529, 48167971737058), 'sobel_mean': (26436775610593, 52873551221187), 'image_tc': (16, 16), 'diff_tc': (29, 29), 'laplace_tc': (25, 25), 'sobel_tc': (25, 25), 'spectral_tc': (16, 16)}" +} \ No newline at end of file diff --git a/tests/test_main_help.py b/tests/test_main_help.py new file mode 100644 index 0000000..db008a5 --- /dev/null +++ b/tests/test_main_help.py @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: MPL-2.0 AND LicenseRef-Commons-Clause-License-Condition-1.0 +# + +"""Test suite for CLI help text.""" + +import argparse +import sys +from io import StringIO +from negate.extract.unified_core import ExtractionModule + + +def test_process_help_includes_all_modules(): + """Verify process command help lists all ExtractionModule options.""" + from negate.__main__ import _load_blurb_text, _load_model_choices, _build_parser + + blurb = _load_blurb_text() + choices = _load_model_choices() + + parser = _build_parser( + blurb=blurb, + choices=choices, + list_results=[], + list_model=[], + inference_pair=[], + ) + + help_output = StringIO() + try: + parser.parse_args(["process", "-h"]) + except SystemExit: + pass + + help_text = parser.format_help() + process_subparser = None + + for action in parser._subparsers._actions: + if isinstance(action, argparse._SubParsersAction): + if "process" in action.choices: + process_subparser = action.choices["process"] + break + + assert process_subparser is not None, "process subparser not found" + + process_help = process_subparser.format_help() + + for module in ExtractionModule: + assert module.name in process_help, f"Module {module.name} not found in process help text" + + +def test_process_help_module_list_matches_enum(): + """Verify the module list in help matches ExtractionModule enum.""" + from negate.__main__ import _load_blurb_text, _load_model_choices, _build_parser + + blurb = _load_blurb_text() + choices = _load_model_choices() + + parser = _build_parser( + blurb=blurb, + choices=choices, + list_results=[], + list_model=[], + inference_pair=[], + ) + + for action in parser._subparsers._actions: + if isinstance(action, argparse._SubParsersAction): + if "process" in action.choices: + process_subparser = action.choices["process"] + break + + process_help = process_subparser.format_help() + + module_names = [mod.name for mod in ExtractionModule] + for module_name in module_names: + assert module_name in process_help, f"Module {module_name} missing from help" + + assert len(module_names) == len(ExtractionModule), "Module list count mismatch"