44
55import json
66from pathlib import Path
7+ from typing import Any , cast
78
89import pytest
9-
1010from python_security_auditing .report import build_markdown , check_thresholds , write_step_summary
1111from python_security_auditing .settings import Settings
1212
1313FIXTURES = Path (__file__ ).parent / "fixtures"
1414
1515
16- def load (name : str ) -> object :
16+ def load (name : str ) -> Any :
1717 return json .loads ((FIXTURES / name ).read_text ())
1818
1919
2020@pytest .fixture ()
21- def bandit_clean () -> dict : # type: ignore[type-arg]
22- return load ("bandit_clean.json" ) # type: ignore[return-value]
21+ def bandit_clean () -> dict [ str , Any ]:
22+ return cast ( dict [ str , Any ], load ("bandit_clean.json" ))
2323
2424
2525@pytest .fixture ()
26- def bandit_issues () -> dict : # type: ignore[type-arg]
27- return load ("bandit_issues.json" ) # type: ignore[return-value]
26+ def bandit_issues () -> dict [ str , Any ]:
27+ return cast ( dict [ str , Any ], load ("bandit_issues.json" ))
2828
2929
3030@pytest .fixture ()
31- def pip_clean () -> list : # type: ignore[type-arg]
32- return load ("pip_audit_clean.json" ) # type: ignore[return-value]
31+ def pip_clean () -> list [ Any ]:
32+ return cast ( list [ Any ], load ("pip_audit_clean.json" ))
3333
3434
3535@pytest .fixture ()
36- def pip_fixable () -> list : # type: ignore[type-arg]
37- return load ("pip_audit_fixable.json" ) # type: ignore[return-value]
36+ def pip_fixable () -> list [ Any ]:
37+ return cast ( list [ Any ], load ("pip_audit_fixable.json" ))
3838
3939
4040@pytest .fixture ()
41- def pip_unfixable () -> list : # type: ignore[type-arg]
42- return load ("pip_audit_unfixable.json" ) # type: ignore[return-value]
41+ def pip_unfixable () -> list [ Any ]:
42+ return cast ( list [ Any ], load ("pip_audit_unfixable.json" ))
4343
4444
4545# ---------------------------------------------------------------------------
4646# check_thresholds
4747# ---------------------------------------------------------------------------
4848
4949
50- def test_clean_no_blocking (bandit_clean : dict , pip_clean : list ) -> None : # type: ignore[type-arg]
50+ def test_clean_no_blocking (bandit_clean : dict [ str , Any ], pip_clean : list [ Any ] ) -> None :
5151 s = Settings ()
5252 assert check_thresholds (bandit_clean , pip_clean , s ) is False
5353
5454
55- def test_bandit_high_blocks (bandit_issues : dict , pip_clean : list ) -> None : # type: ignore[type-arg]
55+ def test_bandit_high_blocks (bandit_issues : dict [ str , Any ], pip_clean : list [ Any ] ) -> None :
5656 s = Settings () # threshold=HIGH
5757 assert check_thresholds (bandit_issues , pip_clean , s ) is True
5858
5959
60- def test_bandit_medium_does_not_block_at_high_threshold (bandit_issues : dict , pip_clean : list ) -> None : # type: ignore[type-arg]
60+ def test_bandit_medium_does_not_block_at_high_threshold (
61+ bandit_issues : dict [str , Any ], pip_clean : list [Any ]
62+ ) -> None :
6163 """bandit_issues has HIGH and MEDIUM; only HIGH should block when threshold=HIGH."""
6264 s = Settings ()
6365 # Remove HIGH results so only MEDIUM remain
@@ -68,7 +70,9 @@ def test_bandit_medium_does_not_block_at_high_threshold(bandit_issues: dict, pip
6870 assert check_thresholds (medium_only , pip_clean , s ) is False
6971
7072
71- def test_bandit_medium_blocks_at_medium_threshold (bandit_issues : dict , pip_clean : list , monkeypatch : pytest .MonkeyPatch ) -> None : # type: ignore[type-arg]
73+ def test_bandit_medium_blocks_at_medium_threshold (
74+ bandit_issues : dict [str , Any ], pip_clean : list [Any ], monkeypatch : pytest .MonkeyPatch
75+ ) -> None :
7276 monkeypatch .setenv ("BANDIT_SEVERITY_THRESHOLD" , "MEDIUM" )
7377 s = Settings ()
7478 medium_only = {
@@ -78,29 +82,39 @@ def test_bandit_medium_blocks_at_medium_threshold(bandit_issues: dict, pip_clean
7882 assert check_thresholds (medium_only , pip_clean , s ) is True
7983
8084
81- def test_pip_fixable_blocks_by_default (bandit_clean : dict , pip_fixable : list ) -> None : # type: ignore[type-arg]
85+ def test_pip_fixable_blocks_by_default (
86+ bandit_clean : dict [str , Any ], pip_fixable : list [Any ]
87+ ) -> None :
8288 s = Settings () # pip_audit_block_on=fixable
8389 assert check_thresholds (bandit_clean , pip_fixable , s ) is True
8490
8591
86- def test_pip_unfixable_does_not_block_on_fixable (bandit_clean : dict , pip_unfixable : list ) -> None : # type: ignore[type-arg]
92+ def test_pip_unfixable_does_not_block_on_fixable (
93+ bandit_clean : dict [str , Any ], pip_unfixable : list [Any ]
94+ ) -> None :
8795 s = Settings () # pip_audit_block_on=fixable
8896 assert check_thresholds (bandit_clean , pip_unfixable , s ) is False
8997
9098
91- def test_pip_unfixable_blocks_on_all (bandit_clean : dict , pip_unfixable : list , monkeypatch : pytest .MonkeyPatch ) -> None : # type: ignore[type-arg]
99+ def test_pip_unfixable_blocks_on_all (
100+ bandit_clean : dict [str , Any ], pip_unfixable : list [Any ], monkeypatch : pytest .MonkeyPatch
101+ ) -> None :
92102 monkeypatch .setenv ("PIP_AUDIT_BLOCK_ON" , "all" )
93103 s = Settings ()
94104 assert check_thresholds (bandit_clean , pip_unfixable , s ) is True
95105
96106
97- def test_pip_fixable_does_not_block_on_none (bandit_clean : dict , pip_fixable : list , monkeypatch : pytest .MonkeyPatch ) -> None : # type: ignore[type-arg]
107+ def test_pip_fixable_does_not_block_on_none (
108+ bandit_clean : dict [str , Any ], pip_fixable : list [Any ], monkeypatch : pytest .MonkeyPatch
109+ ) -> None :
98110 monkeypatch .setenv ("PIP_AUDIT_BLOCK_ON" , "none" )
99111 s = Settings ()
100112 assert check_thresholds (bandit_clean , pip_fixable , s ) is False
101113
102114
103- def test_bandit_only_tool_skips_pip (bandit_issues : dict , pip_fixable : list , monkeypatch : pytest .MonkeyPatch ) -> None : # type: ignore[type-arg]
115+ def test_bandit_only_tool_skips_pip (
116+ bandit_issues : dict [str , Any ], pip_fixable : list [Any ], monkeypatch : pytest .MonkeyPatch
117+ ) -> None :
104118 monkeypatch .setenv ("TOOLS" , "bandit" )
105119 s = Settings ()
106120 # pip-audit not in enabled tools, so fixable vulns should not block
@@ -109,15 +123,19 @@ def test_bandit_only_tool_skips_pip(bandit_issues: dict, pip_fixable: list, monk
109123 assert result is True
110124
111125
112- def test_pip_only_tool_skips_bandit (bandit_issues : dict , pip_fixable : list , monkeypatch : pytest .MonkeyPatch ) -> None : # type: ignore[type-arg]
126+ def test_pip_only_tool_skips_bandit (
127+ bandit_issues : dict [str , Any ], pip_fixable : list [Any ], monkeypatch : pytest .MonkeyPatch
128+ ) -> None :
113129 monkeypatch .setenv ("TOOLS" , "pip-audit" )
114130 s = Settings ()
115131 # bandit not in enabled tools, bandit HIGH issues should not block
116132 result = check_thresholds (bandit_issues , pip_fixable , s )
117133 assert result is True # pip-audit fixable issues do block
118134
119135
120- def test_pip_only_no_bandit_blocking (bandit_issues : dict , pip_clean : list , monkeypatch : pytest .MonkeyPatch ) -> None : # type: ignore[type-arg]
136+ def test_pip_only_no_bandit_blocking (
137+ bandit_issues : dict [str , Any ], pip_clean : list [Any ], monkeypatch : pytest .MonkeyPatch
138+ ) -> None :
121139 monkeypatch .setenv ("TOOLS" , "pip-audit" )
122140 s = Settings ()
123141 assert check_thresholds (bandit_issues , pip_clean , s ) is False
@@ -128,41 +146,43 @@ def test_pip_only_no_bandit_blocking(bandit_issues: dict, pip_clean: list, monke
128146# ---------------------------------------------------------------------------
129147
130148
131- def test_markdown_contains_header (bandit_clean : dict , pip_clean : list ) -> None : # type: ignore[type-arg]
149+ def test_markdown_contains_header (bandit_clean : dict [ str , Any ], pip_clean : list [ Any ] ) -> None :
132150 s = Settings ()
133151 md = build_markdown (bandit_clean , pip_clean , s )
134152 assert "# Security Audit Report" in md
135153
136154
137- def test_markdown_clean_result (bandit_clean : dict , pip_clean : list ) -> None : # type: ignore[type-arg]
155+ def test_markdown_clean_result (bandit_clean : dict [ str , Any ], pip_clean : list [ Any ] ) -> None :
138156 s = Settings ()
139157 md = build_markdown (bandit_clean , pip_clean , s )
140158 assert "No blocking issues found" in md
141159 assert "✅" in md
142160
143161
144- def test_markdown_blocking_result (bandit_issues : dict , pip_clean : list ) -> None : # type: ignore[type-arg]
162+ def test_markdown_blocking_result (bandit_issues : dict [ str , Any ], pip_clean : list [ Any ] ) -> None :
145163 s = Settings ()
146164 md = build_markdown (bandit_issues , pip_clean , s )
147165 assert "Blocking issues found" in md
148166 assert "❌" in md
149167
150168
151- def test_markdown_bandit_table (bandit_issues : dict , pip_clean : list ) -> None : # type: ignore[type-arg]
169+ def test_markdown_bandit_table (bandit_issues : dict [ str , Any ], pip_clean : list [ Any ] ) -> None :
152170 s = Settings ()
153171 md = build_markdown (bandit_issues , pip_clean , s )
154172 assert "B404" in md
155173 assert "src/app.py" in md
156174
157175
158- def test_markdown_pip_table (bandit_clean : dict , pip_fixable : list ) -> None : # type: ignore[type-arg]
176+ def test_markdown_pip_table (bandit_clean : dict [ str , Any ], pip_fixable : list [ Any ] ) -> None :
159177 s = Settings ()
160178 md = build_markdown (bandit_clean , pip_fixable , s )
161179 assert "requests" in md
162180 assert "GHSA-j8r2-6x86-q33q" in md
163181
164182
165- def test_markdown_run_url (bandit_clean : dict , pip_clean : list , monkeypatch : pytest .MonkeyPatch ) -> None : # type: ignore[type-arg]
183+ def test_markdown_run_url (
184+ bandit_clean : dict [str , Any ], pip_clean : list [Any ], monkeypatch : pytest .MonkeyPatch
185+ ) -> None :
166186 monkeypatch .setenv ("GITHUB_REPOSITORY" , "org/repo" )
167187 monkeypatch .setenv ("GITHUB_RUN_ID" , "999" )
168188 s = Settings ()
0 commit comments