From 1f25b31c7e7671c49319063b6db510c269d4d748 Mon Sep 17 00:00:00 2001 From: Villon CHEN Date: Tue, 16 Dec 2025 14:44:03 +0100 Subject: [PATCH 1/6] feat(CLI): remove completion related command if installed --- codesectools/cli.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/codesectools/cli.py b/codesectools/cli.py index 425e73c..12a85fe 100755 --- a/codesectools/cli.py +++ b/codesectools/cli.py @@ -5,9 +5,11 @@ """ import os +from pathlib import Path from typing import Optional import typer +import typer.completion import typer.core from click import Choice from rich import print @@ -19,7 +21,21 @@ from codesectools.sasts.all.cli import build_cli as build_all_sast_cli from codesectools.sasts.core.sast.requirements import DownloadableRequirement -cli = typer.Typer(name="cstools", no_args_is_help=True) +typer.completion.completion_init() + +CLI_NAME = "cstools" + +COMPLETION_FILE = [ + Path.home() / ".bash_completions" / f"{CLI_NAME}.sh", + Path.home() / f".zfunc/_{CLI_NAME}", + Path.home() / f".config/fish/completions/{CLI_NAME}.fish", +] + +cli = typer.Typer( + name=CLI_NAME, + no_args_is_help=True, + add_completion=not any(f.is_file() for f in COMPLETION_FILE), +) def version_callback(value: bool) -> None: From 4b220b781c537b26a0b39635d5dda7273b76c7b9 Mon Sep 17 00:00:00 2001 From: Villon CHEN Date: Tue, 16 Dec 2025 14:44:23 +0100 Subject: [PATCH 2/6] style(CLI): shorten description --- codesectools/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codesectools/cli.py b/codesectools/cli.py index 12a85fe..56c6719 100755 --- a/codesectools/cli.py +++ b/codesectools/cli.py @@ -67,7 +67,7 @@ def main( ), ] = None, ) -> None: - """CodeSecTools: A framework for code security that provides abstractions for static analysis tools and datasets to support their integration, testing, and evaluation.""" + """CodeSecTools CLI.""" if debug: os.environ["DEBUG"] = "1" os.environ["_TYPER_STANDARD_TRACEBACK"] = "1" From 1e278c55ec613c6df65fae09b4a6b5e26c458585 Mon Sep 17 00:00:00 2001 From: Villon CHEN Date: Tue, 16 Dec 2025 14:48:24 +0100 Subject: [PATCH 3/6] feat(CLI)!: remove help command as `no_args_is_help` is true --- codesectools/cli.py | 1 + codesectools/sasts/all/cli.py | 2 +- codesectools/sasts/core/cli.py | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/codesectools/cli.py b/codesectools/cli.py index 56c6719..34e856f 100755 --- a/codesectools/cli.py +++ b/codesectools/cli.py @@ -34,6 +34,7 @@ cli = typer.Typer( name=CLI_NAME, no_args_is_help=True, + add_help_option=False, add_completion=not any(f.is_file() for f in COMPLETION_FILE), ) diff --git a/codesectools/sasts/all/cli.py b/codesectools/sasts/all/cli.py index 5282736..352191f 100644 --- a/codesectools/sasts/all/cli.py +++ b/codesectools/sasts/all/cli.py @@ -18,7 +18,7 @@ def build_cli() -> typer.Typer: """Build the Typer CLI for running all SAST tools.""" - cli = typer.Typer(name="allsast", no_args_is_help=True) + cli = typer.Typer(name="allsast", no_args_is_help=True, add_help_option=False) all_sast = AllSAST() @cli.callback() diff --git a/codesectools/sasts/core/cli.py b/codesectools/sasts/core/cli.py index 41baf60..b53ca51 100644 --- a/codesectools/sasts/core/cli.py +++ b/codesectools/sasts/core/cli.py @@ -51,7 +51,9 @@ def __init__(self, sast: SAST, custom_messages: dict) -> None: def build_cli(self) -> typer.Typer: """Build and return the Typer CLI application for the SAST tool.""" - self.cli = typer.Typer(name=self.sast.name.lower(), no_args_is_help=True) + self.cli = typer.Typer( + name=self.sast.name.lower(), no_args_is_help=True, add_help_option=False + ) self._add_minimal() return self.cli From eb806ae13b9804aa8726d5565f6c345a77352e03 Mon Sep 17 00:00:00 2001 From: Villon CHEN Date: Tue, 16 Dec 2025 14:50:18 +0100 Subject: [PATCH 4/6] chore(release): bump project version --- pyproject.toml | 2 +- requirements.txt | 92 ++++++++++++++++++++---------------------------- uv.lock | 2 +- 3 files changed, 40 insertions(+), 56 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e117248..80cf002 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "CodeSecTools" -version = "0.13.7" +version = "0.13.8" description = "A framework for code security that provides abstractions for static analysis tools and datasets to support their integration, testing, and evaluation." readme = "README.md" license = "AGPL-3.0-only" diff --git a/requirements.txt b/requirements.txt index 69e2a07..640f4cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -129,57 +129,41 @@ cycler==0.12.1 \ --hash=sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 \ --hash=sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c # via matplotlib -fonttools==4.61.0 \ - --hash=sha256:0011d640afa61053bc6590f9a3394bd222de7cfde19346588beabac374e9d8ac \ - --hash=sha256:02bdf8e04d1a70476564b8640380f04bb4ac74edc1fc71f1bacb840b3e398ee9 \ - --hash=sha256:0bdcf2e29d65c26299cc3d502f4612365e8b90a939f46cd92d037b6cb7bb544a \ - --hash=sha256:13e3e20a5463bfeb77b3557d04b30bd6a96a6bb5c15c7b2e7908903e69d437a0 \ - --hash=sha256:14a290c5c93fcab76b7f451e6a4b7721b712d90b3b5ed6908f1abcf794e90d6d \ - --hash=sha256:14fafda386377b6131d9e448af42d0926bad47e038de0e5ba1d58c25d621f028 \ - --hash=sha256:1cfa2eb9bae650e58f0e8ad53c49d19a844d6034d6b259f30f197238abc1ccee \ - --hash=sha256:276f14c560e6f98d24ef7f5f44438e55ff5a67f78fa85236b218462c9f5d0635 \ - --hash=sha256:2cb5e45a824ce14b90510024d0d39dae51bd4fbb54c42a9334ea8c8cf4d95cbe \ - --hash=sha256:2de14557d113faa5fb519f7f29c3abe4d69c17fe6a5a2595cc8cda7338029219 \ - --hash=sha256:2f0bafc8a3b3749c69cc610e5aa3da832d39c2a37a68f03d18ec9a02ecaac04a \ - --hash=sha256:328a9c227984bebaf69f3ac9062265f8f6acc7ddf2e4e344c63358579af0aa3d \ - --hash=sha256:3b2065d94e5d63aafc2591c8b6ccbdb511001d9619f1bca8ad39b745ebeb5efa \ - --hash=sha256:4238120002e68296d55e091411c09eab94e111c8ce64716d17df53fd0eb3bb3d \ - --hash=sha256:46cb3d9279f758ac0cf671dc3482da877104b65682679f01b246515db03dbb72 \ - --hash=sha256:58b4f1b78dfbfe855bb8a6801b31b8cdcca0e2847ec769ad8e0b0b692832dd3b \ - --hash=sha256:59587bbe455dbdf75354a9dbca1697a35a8903e01fab4248d6b98a17032cee52 \ - --hash=sha256:5a9b78da5d5faa17e63b2404b77feeae105c1b7e75f26020ab7a27b76e02039f \ - --hash=sha256:627216062d90ab0d98215176d8b9562c4dd5b61271d35f130bcd30f6a8aaa33a \ - --hash=sha256:63c7125d31abe3e61d7bb917329b5543c5b3448db95f24081a13aaf064360fc8 \ - --hash=sha256:6781e7a4bb010be1cd69a29927b0305c86b843395f2613bdabe115f7d6ea7f34 \ - --hash=sha256:67d841aa272be5500de7f447c40d1d8452783af33b4c3599899319f6ef9ad3c1 \ - --hash=sha256:68704a8bbe0b61976262b255e90cde593dc0fe3676542d9b4d846bad2a890a76 \ - --hash=sha256:6b493c32d2555e9944ec1b911ea649ff8f01a649ad9cba6c118d6798e932b3f0 \ - --hash=sha256:6e5ca8c62efdec7972dfdfd454415c4db49b89aeaefaaacada432f3b7eea9866 \ - --hash=sha256:70e2a0c0182ee75e493ef33061bfebf140ea57e035481d2f95aa03b66c7a0e05 \ - --hash=sha256:787ef9dfd1ea9fe49573c272412ae5f479d78e671981819538143bec65863865 \ - --hash=sha256:7b446623c9cd5f14a59493818eaa80255eec2468c27d2c01b56e05357c263195 \ - --hash=sha256:7fb5b84f48a6a733ca3d7f41aa9551908ccabe8669ffe79586560abcc00a9cfd \ - --hash=sha256:9064b0f55b947e929ac669af5311ab1f26f750214db6dd9a0c97e091e918f486 \ - --hash=sha256:96dfc9bc1f2302224e48e6ee37e656eddbab810b724b52e9d9c13a57a6abad01 \ - --hash=sha256:9821ed77bb676736b88fa87a737c97b6af06e8109667e625a4f00158540ce044 \ - --hash=sha256:a32a16951cbf113d38f1dd8551b277b6e06e0f6f776fece0f99f746d739e1be3 \ - --hash=sha256:a5c5fff72bf31b0e558ed085e4fd7ed96eb85881404ecc39ed2a779e7cf724eb \ - --hash=sha256:ad751319dc532a79bdf628b8439af167181b4210a0cd28a8935ca615d9fdd727 \ - --hash=sha256:adbb4ecee1a779469a77377bbe490565effe8fce6fb2e6f95f064de58f8bac85 \ - --hash=sha256:b2b734d8391afe3c682320840c8191de9bd24e7eb85768dd4dc06ed1b63dbb1b \ - --hash=sha256:b5ca59b7417d149cf24e4c1933c9f44b2957424fc03536f132346d5242e0ebe5 \ - --hash=sha256:b6ceac262cc62bec01b3bb59abccf41b24ef6580869e306a4e88b7e56bb4bdda \ - --hash=sha256:ba774b8cbd8754f54b8eb58124e8bd45f736b2743325ab1a5229698942b9b433 \ - --hash=sha256:c53b47834ae41e8e4829171cc44fec0fdf125545a15f6da41776b926b9645a9a \ - --hash=sha256:c84b430616ed73ce46e9cafd0bf0800e366a3e02fb7e1ad7c1e214dbe3862b1f \ - --hash=sha256:dc25a4a9c1225653e4431a9413d0381b1c62317b0f543bdcec24e1991f612f33 \ - --hash=sha256:df8cbce85cf482eb01f4551edca978c719f099c623277bda8332e5dbe7dba09d \ - --hash=sha256:e074bc07c31406f45c418e17c1722e83560f181d122c412fa9e815df0ff74810 \ - --hash=sha256:e0d87e81e4d869549585ba0beb3f033718501c1095004f5e6aef598d13ebc216 \ - --hash=sha256:e24a1565c4e57111ec7f4915f8981ecbb61adf66a55f378fdc00e206059fcfef \ - --hash=sha256:e2bfacb5351303cae9f072ccf3fc6ecb437a6f359c0606bae4b1ab6715201d87 \ - --hash=sha256:e6cd0d9051b8ddaf7385f99dd82ec2a058e2b46cf1f1961e68e1ff20fcbb61af \ - --hash=sha256:ec520a1f0c7758d7a858a00f090c1745f6cde6a7c5e76fb70ea4044a15f712e7 +fonttools==4.60.1 \ + --hash=sha256:022beaea4b73a70295b688f817ddc24ed3e3418b5036ffcd5658141184ef0d0c \ + --hash=sha256:026290e4ec76583881763fac284aca67365e0be9f13a7fb137257096114cb3bc \ + --hash=sha256:1410155d0e764a4615774e5c2c6fc516259fe3eca5882f034eb9bfdbee056259 \ + --hash=sha256:145daa14bf24824b677b9357c5e44fd8895c2a8f53596e1b9ea3496081dc692c \ + --hash=sha256:154cb6ee417e417bf5f7c42fe25858c9140c26f647c7347c06f0cc2d47eff003 \ + --hash=sha256:2299df884c11162617a66b7c316957d74a18e3758c0274762d2cc87df7bc0272 \ + --hash=sha256:2409d5fb7b55fd70f715e6d34e7a6e4f7511b8ad29a49d6df225ee76da76dd77 \ + --hash=sha256:5664fd1a9ea7f244487ac8f10340c4e37664675e8667d6fee420766e0fb3cf08 \ + --hash=sha256:583b7f8e3c49486e4d489ad1deacfb8d5be54a8ef34d6df824f6a171f8511d99 \ + --hash=sha256:66929e2ea2810c6533a5184f938502cfdaea4bc3efb7130d8cc02e1c1b4108d6 \ + --hash=sha256:6ec722ee589e89a89f5b7574f5c45604030aa6ae24cb2c751e2707193b466fed \ + --hash=sha256:6f68576bb4bbf6060c7ab047b1574a1ebe5c50a17de62830079967b211059ebb \ + --hash=sha256:7b0c6d57ab00dae9529f3faf187f2254ea0aa1e04215cf2f1a8ec277c96661bc \ + --hash=sha256:8177ec9676ea6e1793c8a084a90b65a9f778771998eb919d05db6d4b1c0b114c \ + --hash=sha256:839565cbf14645952d933853e8ade66a463684ed6ed6c9345d0faf1f0e868877 \ + --hash=sha256:875cb7764708b3132637f6c5fb385b16eeba0f7ac9fa45a69d35e09b47045801 \ + --hash=sha256:8a44788d9d91df72d1a5eac49b31aeb887a5f4aab761b4cffc4196c74907ea85 \ + --hash=sha256:906306ac7afe2156fcf0042173d6ebbb05416af70f6b370967b47f8f00103bbb \ + --hash=sha256:992775c9fbe2cf794786fa0ffca7f09f564ba3499b8fe9f2f80bd7197db60383 \ + --hash=sha256:996a4d1834524adbb423385d5a629b868ef9d774670856c63c9a0408a3063401 \ + --hash=sha256:9d0ced62b59e0430b3690dbc5373df1c2aa7585e9a8ce38eff87f0fd993c5b01 \ + --hash=sha256:a184b2ea57b13680ab6d5fbde99ccef152c95c06746cb7718c583abd8f945ccc \ + --hash=sha256:a3db56f153bd4c5c2b619ab02c5db5192e222150ce5a1bc10f16164714bc39ac \ + --hash=sha256:a46b2f450bc79e06ef3b6394f0c68660529ed51692606ad7f953fc2e448bc903 \ + --hash=sha256:a884aef09d45ba1206712c7dbda5829562d3fea7726935d3289d343232ecb0d3 \ + --hash=sha256:b2cf105cee600d2de04ca3cfa1f74f1127f8455b71dbad02b9da6ec266e116d6 \ + --hash=sha256:b33a7884fabd72bdf5f910d0cf46be50dce86a0362a65cfc746a4168c67eb96c \ + --hash=sha256:b6379e7546ba4ae4b18f8ae2b9bc5960936007a1c0e30b342f662577e8bc3299 \ + --hash=sha256:c8651e0d4b3bdeda6602b85fdc2abbefc1b41e573ecb37b6779c4ca50753a199 \ + --hash=sha256:e852d9dda9f93ad3651ae1e3bb770eac544ec93c3807888798eccddf84596537 \ + --hash=sha256:eedacb5c5d22b7097482fa834bda0dafa3d914a4e829ec83cdea2a01f8c813c4 \ + --hash=sha256:ef00af0439ebfee806b25f24c8f92109157ff3fac5731dc7867957812e87b8d9 \ + --hash=sha256:f0e8817c7d1a0c2eedebf57ef9a9896f3ea23324769a9a2061a80fe8852705ed \ + --hash=sha256:f3d5be054c461d6a2268831f04091dc82753176f6ea06dc6047a5e168265a987 # via matplotlib gitdb==4.0.12 \ --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ @@ -596,9 +580,9 @@ typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 # via typer -urllib3==2.6.0 \ - --hash=sha256:c90f7a39f716c572c4e3e58509581ebd83f9b59cced005b7db7ad2d22b0db99f \ - --hash=sha256:cb9bcef5a4b345d5da5d145dc3e30834f58e8018828cbc724d30b4cb7d4d49f1 +urllib3==2.5.0 \ + --hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \ + --hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc # via requests xmltodict==1.0.2 \ --hash=sha256:54306780b7c2175a3967cad1db92f218207e5bc1aba697d887807c0fb68b7649 \ diff --git a/uv.lock b/uv.lock index e9cb1bc..908262a 100644 --- a/uv.lock +++ b/uv.lock @@ -221,7 +221,7 @@ wheels = [ [[package]] name = "codesectools" -version = "0.13.7" +version = "0.13.8" source = { editable = "." } dependencies = [ { name = "gitpython" }, From e852fb3121dccbd7dd8544806306cae813b18887 Mon Sep 17 00:00:00 2001 From: Villon CHEN Date: Tue, 16 Dec 2025 15:36:32 +0100 Subject: [PATCH 5/6] fix(tests): remove `--help` flags to test `no_args_is_help` --- tests/test_cli.py | 2 +- tests/test_sasts.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 335e307..f1a3b3f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -13,7 +13,7 @@ def test_help() -> None | AssertionError: """Test the '--help' option.""" - result = runner.invoke(cli, ["--help"]) + result = runner.invoke(cli) assert result.exit_code == 0 assert "version" in result.output assert "status" in result.output diff --git a/tests/test_sasts.py b/tests/test_sasts.py index 38df9ef..046d1b9 100644 --- a/tests/test_sasts.py +++ b/tests/test_sasts.py @@ -89,7 +89,7 @@ def test_sasts() -> None | AssertionError: for sast_name, sast_data in SASTS_ALL.items(): logging.info(f"Checking {sast_name} commands") sast_cli = sast_data["cli_factory"].build_cli() - result = runner.invoke(sast_cli, ["--help"]) + result = runner.invoke(sast_cli) if sast_data["status"] == "full": assert result.exit_code == 0 assert all( From c29effe34631516581b8830b640aa1c41bfa2cef Mon Sep 17 00:00:00 2001 From: Villon CHEN Date: Tue, 16 Dec 2025 15:37:42 +0100 Subject: [PATCH 6/6] fix(tests): change expected return code to 2 This is due to recent changes in Click>=8.2 https://github.com/pallets/click/commit/d8763b93 --- tests/test_cli.py | 2 +- tests/test_sasts.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index f1a3b3f..c42f194 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -14,7 +14,7 @@ def test_help() -> None | AssertionError: """Test the '--help' option.""" result = runner.invoke(cli) - assert result.exit_code == 0 + assert result.exit_code == 2 assert "version" in result.output assert "status" in result.output diff --git a/tests/test_sasts.py b/tests/test_sasts.py index 046d1b9..7630b63 100644 --- a/tests/test_sasts.py +++ b/tests/test_sasts.py @@ -90,22 +90,20 @@ def test_sasts() -> None | AssertionError: logging.info(f"Checking {sast_name} commands") sast_cli = sast_data["cli_factory"].build_cli() result = runner.invoke(sast_cli) + assert result.exit_code == 2 if sast_data["status"] == "full": - assert result.exit_code == 0 assert all( command in result.output for command in ["analyze", "benchmark", "list", "plot"] ) elif sast_data["status"] == "partial": - assert result.exit_code == 0 assert all( command in result.output for command in ["install", "list", "plot"] ) elif sast_data["status"] == "none": - assert result.exit_code == 0 assert all(command in result.output for command in ["install"]) else: - assert result.exit_code != 0 + assert result.exit_code != 2 SAST_RESULTS = {sast_name: [] for sast_name in SASTS_ALL}