Skip to content

Commit c040a1b

Browse files
authored
Update type checking (#427)
1 parent 375621b commit c040a1b

9 files changed

Lines changed: 50 additions & 38 deletions

File tree

.github/workflows/build-release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ name: "Build release artifacts"
4040

4141
permissions: {}
4242

43-
# Set from inputs for workflow_dispatch, or set defaults to test push/PR events
4443
env:
44+
FORCE_COLOR: 1
45+
# Set from inputs for workflow_dispatch, or set defaults to test push/PR events
4546
GIT_REMOTE: ${{ github.event.inputs.git_remote || 'python' }}
4647
GIT_COMMIT: ${{ github.event.inputs.git_commit || '55ea59e7dc35e1363b203ae4dd9cfc3a0ac0a844' }}
4748
CPYTHON_RELEASE: ${{ github.event.inputs.cpython_release || '3.15.0a8' }}

mypy-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ pyfakefs
55
pytest
66
pytest-mock
77
python-gnupg # untyped :(
8+
requests>=2.34
89
sigstore==4.5.0
910
types-paramiko
10-
types-requests

pyproject.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,5 @@ extra_checks = true
1313
warn_unreachable = true
1414

1515
exclude = [
16-
"^tests/test_release_tag.py$",
17-
"^tests/test_run_release.py$",
18-
"^tests/test_sbom.py$",
1916
"^windows-release/merge-and-upload.py$",
20-
"^windows-release/purge.py$",
2117
]

requirements.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ alive_progress>=3.3.0
55
python-gnupg
66
aiohttp
77
blurb>=1.2.1
8+
requests>=2.34
89
sigstore>=4.5.0

requirements.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,10 @@ pyopenssl==26.0.0 \
890890
python-gnupg==0.5.6 \
891891
--hash=sha256:b5050a55663d8ab9fcc8d97556d229af337a87a3ebebd7054cbd8b7e2043394a
892892
# via -r requirements.in
893-
requests==2.33.0 \
894-
--hash=sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b
893+
requests==2.34.2 \
894+
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0
895895
# via
896+
# -r requirements.in
896897
# id
897898
# sigstore
898899
rfc3161-client==1.0.6 \

tests/test_release_tag.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,14 @@ def test_tag_committed_at_not_found() -> None:
7474

7575
# Act / Assert
7676
with pytest.raises(SystemExit):
77-
tag.committed_at()
77+
tag.committed_at
7878

7979

8080
def test_tag_committed(mocker: MockerFixture) -> None:
8181
# Arrange
8282
tag = release.Tag("3.12.2")
8383

84-
proc = CompletedProcess([], 0)
85-
proc.stdout = b"1707250784"
84+
proc = CompletedProcess([], 0, stdout=b"1707250784")
8685
mocker.patch("subprocess.run", return_value=proc)
8786

8887
# Act / Assert
@@ -156,7 +155,7 @@ def test_tag_long_name() -> None:
156155
],
157156
)
158157
def test_tag_is_security_release(
159-
version: str, expected: str, mocker: MockerFixture
158+
version: str, expected: bool, mocker: MockerFixture
160159
) -> None:
161160
# Arrange
162161
mock_response = b"""

tests/test_run_release.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import contextlib
33
import io
44
import tarfile
5+
from collections.abc import Iterator
56
from contextlib import nullcontext as does_not_raise
67
from pathlib import Path
7-
from typing import cast
8+
from typing import Any, cast
89

910
import pytest
1011

@@ -17,7 +18,7 @@
1718
"version",
1819
["sigstore 4.0.0", "sigstore 4.1.0"],
1920
)
20-
def test_check_sigstore_version_success(version) -> None:
21+
def test_check_sigstore_version_success(version: str) -> None:
2122
# Verify runs with no exceptions
2223
run_release.check_sigstore_version(version)
2324

@@ -26,7 +27,7 @@ def test_check_sigstore_version_success(version) -> None:
2627
"version",
2728
["sigstore 3.4.0", "sigstore 3.6.2", "sigstore 3.6.6", ""],
2829
)
29-
def test_check_sigstore_version_exception(version) -> None:
30+
def test_check_sigstore_version_exception(version: str) -> None:
3031
with pytest.raises(
3132
ReleaseException, match="Sigstore version not detected or not valid"
3233
):
@@ -89,13 +90,15 @@ def test_invalid_extract_github_owner() -> None:
8990
],
9091
)
9192
def test_check_cpython_repo_branch(
92-
monkeypatch, release_tag: str, git_current_branch: str, expectation
93+
monkeypatch: pytest.MonkeyPatch,
94+
release_tag: str,
95+
git_current_branch: str,
96+
expectation: contextlib.AbstractContextManager[object],
9397
) -> None:
9498
# Arrange
9599
db = {"release": Tag(release_tag), "git_repo": "/fake/repo"}
96100
monkeypatch.setattr(
97-
run_release.subprocess,
98-
"check_output",
101+
"run_release.subprocess.check_output",
99102
lambda *args, **kwargs: git_current_branch,
100103
)
101104

@@ -116,23 +119,26 @@ def test_check_cpython_repo_branch(
116119
],
117120
)
118121
def test_check_cpython_repo_age(
119-
monkeypatch, age_seconds: int, user_continues: bool | None, expectation
122+
monkeypatch: pytest.MonkeyPatch,
123+
age_seconds: int,
124+
user_continues: bool | None,
125+
expectation: contextlib.AbstractContextManager[object],
120126
) -> None:
121127
# Arrange
122128
db = {"release": Tag("3.15.0a6"), "git_repo": "/fake/repo"}
123129
current_time = 1700000000
124130
commit_timestamp = current_time - age_seconds
125131

126-
def fake_check_output(cmd, **kwargs):
132+
def fake_check_output(cmd: list[str], **kwargs: Any) -> str:
127133
cmd_str = " ".join(cmd)
128134
if "%ct" in cmd_str:
129135
return f"{commit_timestamp}\n"
130136
if "%cr" in cmd_str:
131137
return "some time ago\n"
132138
return ""
133139

134-
monkeypatch.setattr(run_release.subprocess, "check_output", fake_check_output)
135-
monkeypatch.setattr(run_release.time, "time", lambda: current_time)
140+
monkeypatch.setattr("run_release.subprocess.check_output", fake_check_output)
141+
monkeypatch.setattr("run_release.time.time", lambda: current_time)
136142
if user_continues is not None:
137143
monkeypatch.setattr(run_release, "ask_question", lambda _: user_continues)
138144

@@ -161,12 +167,12 @@ def prepare_fake_docs(tmp_path: Path, content: str) -> None:
161167

162168

163169
@contextlib.contextmanager
164-
def fake_answers(monkeypatch: pytest.MonkeyPatch, answers: list[str]) -> None:
170+
def fake_answers(monkeypatch: pytest.MonkeyPatch, answers: list[str]) -> Iterator[None]:
165171
"""Monkey-patch input() to give the given answers. All must be consumed."""
166172

167173
answers_left = list(answers)
168174

169-
def fake_input(question):
175+
def fake_input(question: str) -> str:
170176
print(question, "--", answers_left[0])
171177
return answers_left.pop(0)
172178

@@ -207,7 +213,9 @@ def test_check_doc_unreleased_version_ok(tmp_path: Path) -> None:
207213
run_release.check_doc_unreleased_version(cast(ReleaseShelf, db))
208214

209215

210-
def test_check_doc_unreleased_version_not_ok(monkeypatch, tmp_path: Path) -> None:
216+
def test_check_doc_unreleased_version_not_ok(
217+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
218+
) -> None:
211219
prepare_fake_docs(
212220
tmp_path,
213221
"<div>New in 3.13.0rc1 (unreleased)</div>",
@@ -220,7 +228,9 @@ def test_check_doc_unreleased_version_not_ok(monkeypatch, tmp_path: Path) -> Non
220228
run_release.check_doc_unreleased_version(cast(ReleaseShelf, db))
221229

222230

223-
def test_check_doc_unreleased_version_waived(monkeypatch, tmp_path: Path) -> None:
231+
def test_check_doc_unreleased_version_waived(
232+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
233+
) -> None:
224234
prepare_fake_docs(
225235
tmp_path,
226236
"<div>New in 3.13.0rc1 (unreleased)</div>",

tests/test_sbom.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
import re
66
import unittest.mock
77
from pathlib import Path
8+
from typing import Any
89

910
import pytest
11+
from pytest_mock import MockerFixture
1012

1113
import sbom
1214

@@ -27,7 +29,7 @@ def test_spdx_id(value: str, expected: str) -> None:
2729
assert sbom.spdx_id(value) == expected
2830

2931

30-
def test_spdx_id_collisions():
32+
def test_spdx_id_collisions() -> None:
3133
sbom._SPDX_IDS_TO_VALUES = {} # Reset the cache.
3234
assert (
3335
sbom.spdx_id("SPDXRef-FILE-Lib/collections.py")
@@ -53,11 +55,13 @@ def test_spdx_id_collisions():
5355
),
5456
],
5557
)
56-
def test_calculate_package_verification_code(package_sha1s, package_verification_code):
58+
def test_calculate_package_verification_code(
59+
package_sha1s: list[str], package_verification_code: str
60+
) -> None:
5761
# Randomize because PackageVerificationCode is deterministic.
5862
random.shuffle(package_sha1s)
5963

60-
input_sbom = {
64+
input_sbom: Any = {
6165
"files": [
6266
{
6367
"SPDXID": f"SPDXRef-FILE-{package_sha1}",
@@ -83,11 +87,11 @@ def test_calculate_package_verification_code(package_sha1s, package_verification
8387
}
8488

8589

86-
def test_normalization():
90+
def test_normalization() -> None:
8791
# Test that arbitrary JSON data can be normalized.
8892
# Normalization doesn't have to make too much sense,
8993
# only needs to be reproducible.
90-
data = {
94+
data: Any = {
9195
"a": [1, 2, 3, {"b": [4, "c", [7, True, "2", {}]]}],
9296
# This line tests that inner structures are sorted first.
9397
"b": [[1, 2, "b"], [2, 1, "a"]],
@@ -99,7 +103,7 @@ def test_normalization():
99103
}
100104

101105

102-
def test_fetch_project_metadata_from_pypi(mocker):
106+
def test_fetch_project_metadata_from_pypi(mocker: MockerFixture) -> None:
103107
mock_urlopen = mocker.patch("sbom.urlopen")
104108
mock_urlopen.return_value = unittest.mock.Mock()
105109

@@ -173,8 +177,8 @@ def test_remove_pip_from_sbom() -> None:
173177
assert sbom_data == expected
174178

175179

176-
def test_create_cpython_sbom():
177-
sbom_data = {"packages": []}
180+
def test_create_cpython_sbom() -> None:
181+
sbom_data: Any = {"packages": []}
178182

179183
artifact_path = str(pathlib.Path(__file__).parent / "fake-artifact.txt")
180184
sbom.create_cpython_sbom(
@@ -240,9 +244,9 @@ def test_create_cpython_sbom():
240244
],
241245
)
242246
def test_create_cpython_sbom_pre_release_download_location(
243-
cpython_version, download_location
244-
):
245-
sbom_data = {"packages": []}
247+
cpython_version: str, download_location: str
248+
) -> None:
249+
sbom_data: Any = {"packages": []}
246250

247251
artifact_path = str(pathlib.Path(__file__).parent / "fake-artifact.txt")
248252
sbom.create_cpython_sbom(

windows-release/purge.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,6 @@
7373
print("Purged:")
7474
for n in PATHS:
7575
u = URL + n
76-
with urlopen(Request(u, method="PURGE", headers={"Fastly-Soft-Purge": 1})) as r:
76+
with urlopen(Request(u, method="PURGE", headers={"Fastly-Soft-Purge": "1"})) as r:
7777
r.read()
7878
print(" ", u)

0 commit comments

Comments
 (0)