Skip to content

Commit 84eb923

Browse files
committed
chore: bump python version
1 parent b33f42f commit 84eb923

6 files changed

Lines changed: 844 additions & 28 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "python-security-auditing"
77
version = "0.1.0"
88
description = "Reusable GitHub Action for Python security auditing with bandit and pip-audit"
99
license = { text = "MIT" }
10-
requires-python = ">=3.11"
10+
requires-python = ">=3.13"
1111
dependencies = [
1212
"pydantic-settings>=2.0",
1313
"bandit>=1.8",
@@ -33,7 +33,7 @@ line-length = 100
3333
select = ["E", "F", "I", "UP"]
3434

3535
[tool.mypy]
36-
python_version = "3.11"
36+
python_version = "3.13"
3737
strict = true
3838

3939
[tool.pytest.ini_options]

src/python_security_auditing/report.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,7 @@ def _bandit_section(report: dict[str, Any], settings: Settings) -> str:
4949
lines.append("✅ No issues found.\n")
5050
return "\n".join(lines)
5151

52-
lines.append(
53-
"| Severity | Confidence | File | Line | Issue |\n"
54-
"|---|---|---|---|---|\n"
55-
)
52+
lines.append("| Severity | Confidence | File | Line | Issue |\n" "|---|---|---|---|---|\n")
5653
for r in results:
5754
sev = r.get("issue_severity", "")
5855
conf = r.get("issue_confidence", "")
@@ -82,8 +79,7 @@ def _pip_audit_section(report: list[dict[str, Any]], settings: Settings) -> str:
8279
return "\n".join(lines)
8380

8481
lines.append(
85-
"| Package | Version | ID | Fix Versions | Description |\n"
86-
"|---|---|---|---|---|\n"
82+
"| Package | Version | ID | Fix Versions | Description |\n" "|---|---|---|---|---|\n"
8783
)
8884
for pkg in vulnerable:
8985
name = pkg.get("name", "")
@@ -95,12 +91,7 @@ def _pip_audit_section(report: list[dict[str, Any]], settings: Settings) -> str:
9591
lines.append(f"| {name} | {version} | {vid} | {fix_versions} | {desc} |")
9692

9793
total_vulns = sum(len(pkg.get("vulns", [])) for pkg in vulnerable)
98-
fixable = sum(
99-
1
100-
for pkg in vulnerable
101-
for v in pkg.get("vulns", [])
102-
if v.get("fix_versions")
103-
)
94+
fixable = sum(1 for pkg in vulnerable for v in pkg.get("vulns", []) if v.get("fix_versions"))
10495
lines.append(
10596
f"\n_{total_vulns} vulnerability/vulnerabilities found "
10697
f"({fixable} fixable) across {len(vulnerable)} package(s)._\n"

tests/test_report.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from pathlib import Path
77

88
import pytest
9-
109
from python_security_auditing.report import build_markdown, check_thresholds, write_step_summary
1110
from python_security_auditing.settings import Settings
1211

@@ -57,7 +56,9 @@ def test_bandit_high_blocks(bandit_issues: dict, pip_clean: list) -> None: # ty
5756
assert check_thresholds(bandit_issues, pip_clean, s) is True
5857

5958

60-
def test_bandit_medium_does_not_block_at_high_threshold(bandit_issues: dict, pip_clean: list) -> None: # type: ignore[type-arg]
59+
def test_bandit_medium_does_not_block_at_high_threshold(
60+
bandit_issues: dict, pip_clean: list
61+
) -> None: # type: ignore[type-arg]
6162
"""bandit_issues has HIGH and MEDIUM; only HIGH should block when threshold=HIGH."""
6263
s = Settings()
6364
# Remove HIGH results so only MEDIUM remain
@@ -68,7 +69,9 @@ def test_bandit_medium_does_not_block_at_high_threshold(bandit_issues: dict, pip
6869
assert check_thresholds(medium_only, pip_clean, s) is False
6970

7071

71-
def test_bandit_medium_blocks_at_medium_threshold(bandit_issues: dict, pip_clean: list, monkeypatch: pytest.MonkeyPatch) -> None: # type: ignore[type-arg]
72+
def test_bandit_medium_blocks_at_medium_threshold(
73+
bandit_issues: dict, pip_clean: list, monkeypatch: pytest.MonkeyPatch
74+
) -> None: # type: ignore[type-arg]
7275
monkeypatch.setenv("BANDIT_SEVERITY_THRESHOLD", "MEDIUM")
7376
s = Settings()
7477
medium_only = {
@@ -88,19 +91,25 @@ def test_pip_unfixable_does_not_block_on_fixable(bandit_clean: dict, pip_unfixab
8891
assert check_thresholds(bandit_clean, pip_unfixable, s) is False
8992

9093

91-
def test_pip_unfixable_blocks_on_all(bandit_clean: dict, pip_unfixable: list, monkeypatch: pytest.MonkeyPatch) -> None: # type: ignore[type-arg]
94+
def test_pip_unfixable_blocks_on_all(
95+
bandit_clean: dict, pip_unfixable: list, monkeypatch: pytest.MonkeyPatch
96+
) -> None: # type: ignore[type-arg]
9297
monkeypatch.setenv("PIP_AUDIT_BLOCK_ON", "all")
9398
s = Settings()
9499
assert check_thresholds(bandit_clean, pip_unfixable, s) is True
95100

96101

97-
def test_pip_fixable_does_not_block_on_none(bandit_clean: dict, pip_fixable: list, monkeypatch: pytest.MonkeyPatch) -> None: # type: ignore[type-arg]
102+
def test_pip_fixable_does_not_block_on_none(
103+
bandit_clean: dict, pip_fixable: list, monkeypatch: pytest.MonkeyPatch
104+
) -> None: # type: ignore[type-arg]
98105
monkeypatch.setenv("PIP_AUDIT_BLOCK_ON", "none")
99106
s = Settings()
100107
assert check_thresholds(bandit_clean, pip_fixable, s) is False
101108

102109

103-
def test_bandit_only_tool_skips_pip(bandit_issues: dict, pip_fixable: list, monkeypatch: pytest.MonkeyPatch) -> None: # type: ignore[type-arg]
110+
def test_bandit_only_tool_skips_pip(
111+
bandit_issues: dict, pip_fixable: list, monkeypatch: pytest.MonkeyPatch
112+
) -> None: # type: ignore[type-arg]
104113
monkeypatch.setenv("TOOLS", "bandit")
105114
s = Settings()
106115
# pip-audit not in enabled tools, so fixable vulns should not block
@@ -109,15 +118,19 @@ def test_bandit_only_tool_skips_pip(bandit_issues: dict, pip_fixable: list, monk
109118
assert result is True
110119

111120

112-
def test_pip_only_tool_skips_bandit(bandit_issues: dict, pip_fixable: list, monkeypatch: pytest.MonkeyPatch) -> None: # type: ignore[type-arg]
121+
def test_pip_only_tool_skips_bandit(
122+
bandit_issues: dict, pip_fixable: list, monkeypatch: pytest.MonkeyPatch
123+
) -> None: # type: ignore[type-arg]
113124
monkeypatch.setenv("TOOLS", "pip-audit")
114125
s = Settings()
115126
# bandit not in enabled tools, bandit HIGH issues should not block
116127
result = check_thresholds(bandit_issues, pip_fixable, s)
117128
assert result is True # pip-audit fixable issues do block
118129

119130

120-
def test_pip_only_no_bandit_blocking(bandit_issues: dict, pip_clean: list, monkeypatch: pytest.MonkeyPatch) -> None: # type: ignore[type-arg]
131+
def test_pip_only_no_bandit_blocking(
132+
bandit_issues: dict, pip_clean: list, monkeypatch: pytest.MonkeyPatch
133+
) -> None: # type: ignore[type-arg]
121134
monkeypatch.setenv("TOOLS", "pip-audit")
122135
s = Settings()
123136
assert check_thresholds(bandit_issues, pip_clean, s) is False
@@ -162,7 +175,9 @@ def test_markdown_pip_table(bandit_clean: dict, pip_fixable: list) -> None: # t
162175
assert "GHSA-j8r2-6x86-q33q" in md
163176

164177

165-
def test_markdown_run_url(bandit_clean: dict, pip_clean: list, monkeypatch: pytest.MonkeyPatch) -> None: # type: ignore[type-arg]
178+
def test_markdown_run_url(
179+
bandit_clean: dict, pip_clean: list, monkeypatch: pytest.MonkeyPatch
180+
) -> None: # type: ignore[type-arg]
166181
monkeypatch.setenv("GITHUB_REPOSITORY", "org/repo")
167182
monkeypatch.setenv("GITHUB_RUN_ID", "999")
168183
s = Settings()

tests/test_runners.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from unittest.mock import MagicMock, patch
88

99
import pytest
10-
1110
from python_security_auditing.runners import generate_requirements, run_bandit, run_pip_audit
1211
from python_security_auditing.settings import Settings
1312

@@ -103,7 +102,9 @@ def test_run_bandit_parses_json(tmp_path: Path, monkeypatch: pytest.MonkeyPatch)
103102
assert report["results"][0]["issue_severity"] == "HIGH"
104103

105104

106-
def test_run_bandit_returns_empty_on_missing_file(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
105+
def test_run_bandit_returns_empty_on_missing_file(
106+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
107+
) -> None:
107108
monkeypatch.chdir(tmp_path)
108109

109110
with patch("python_security_auditing.runners.subprocess.run") as mock_run:
@@ -146,7 +147,9 @@ def test_run_pip_audit_parses_json(tmp_path: Path, monkeypatch: pytest.MonkeyPat
146147
assert (tmp_path / "pip-audit-report.json").exists()
147148

148149

149-
def test_run_pip_audit_returns_empty_on_no_output(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
150+
def test_run_pip_audit_returns_empty_on_no_output(
151+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
152+
) -> None:
150153
monkeypatch.chdir(tmp_path)
151154

152155
with patch("python_security_auditing.runners.subprocess.run") as mock_run:
@@ -156,7 +159,9 @@ def test_run_pip_audit_returns_empty_on_no_output(tmp_path: Path, monkeypatch: p
156159
assert report == []
157160

158161

159-
def test_run_pip_audit_uses_requirements_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
162+
def test_run_pip_audit_uses_requirements_path(
163+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
164+
) -> None:
160165
monkeypatch.chdir(tmp_path)
161166
req_path = tmp_path / "custom-reqs.txt"
162167

tests/test_settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Tests for settings.py — env var parsing and computed properties."""
22

33
import pytest
4-
54
from python_security_auditing.settings import Settings
65

76

0 commit comments

Comments
 (0)