Skip to content

Commit 9198166

Browse files
mypy: add config and enforce in ci
1 parent 9fb1be7 commit 9198166

6 files changed

Lines changed: 86 additions & 8 deletions

File tree

.github/workflows/ci.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,45 @@ env:
1414
VCPKG_COMMIT: "66c0373dc7fca549e5803087b9487edfe3aca0a1"
1515

1616
jobs:
17+
python-typecheck:
18+
name: Python Type Checking (mypy)
19+
runs-on: ubuntu-24.04
20+
timeout-minutes: 10
21+
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
with:
26+
submodules: recursive
27+
28+
- name: Validate requirements lockfile
29+
shell: bash
30+
run: |
31+
set -euo pipefail
32+
LOCKFILE="requirements-lock.txt"
33+
test -f "$LOCKFILE"
34+
if od -An -tx1 "$LOCKFILE" | tr -s ' ' '\n' | grep -qx '00'; then
35+
echo "ERROR: $LOCKFILE contains NUL bytes (binary corruption)" >&2
36+
exit 1
37+
fi
38+
iconv -f UTF-8 -t UTF-8 "$LOCKFILE" > /dev/null 2>&1
39+
echo "OK: $LOCKFILE is valid UTF-8 and contains no NUL bytes"
40+
41+
- name: Setup Python and dependencies
42+
uses: actions/setup-python@v5
43+
with:
44+
python-version: "3.12"
45+
cache: "pip"
46+
cache-dependency-path: requirements-lock.txt
47+
48+
- name: Install Python dependencies
49+
run: |
50+
python -m pip install --upgrade pip
51+
python -m pip install -r requirements-lock.txt
52+
53+
- name: Run mypy
54+
run: mypy tests
55+
1756
linux-release:
1857
name: ${{ matrix.lane }}
1958
runs-on: ubuntu-24.04

examples/inert_mode/test_inert.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import sys
1515
import time
1616
from pathlib import Path
17+
from typing import Any, cast
1718

1819
# Add protocol_pb2 to path
1920
build_dir = Path(__file__).parent.parent.parent / "build"
@@ -24,12 +25,18 @@
2425
sys.path.insert(0, str(build_dir))
2526

2627
try:
27-
from protocol_pb2 import Request, Response, Value, ValueType
28+
import protocol_pb2 as _protocol
2829
except ImportError:
2930
print("ERROR: protocol_pb2.py not found in build directory")
3031
print("Solution: Rebuild with: .\\scripts\\build.ps1 -Release")
3132
sys.exit(1)
3233

34+
protocol = cast(Any, _protocol)
35+
Request = protocol.Request
36+
Response = protocol.Response
37+
Value = protocol.Value
38+
ValueType = protocol.ValueType
39+
3340

3441
def run_inert_example():
3542
# Find provider executable
@@ -180,7 +187,8 @@ def run_inert_example():
180187
traceback.print_exc()
181188
return False
182189
finally:
183-
provider.stdin.close()
190+
if provider.stdin is not None:
191+
provider.stdin.close()
184192
provider.terminate()
185193
provider.wait(timeout=2)
186194

examples/non_interacting_mode/test_non_interacting.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import sys
1515
import time
1616
from pathlib import Path
17+
from typing import Any, cast
1718

1819
# Add protocol_pb2 to path
1920
build_dir = Path(__file__).parent.parent.parent / "build"
@@ -24,12 +25,18 @@
2425
sys.path.insert(0, str(build_dir))
2526

2627
try:
27-
from protocol_pb2 import Request, Response, Value, ValueType
28+
import protocol_pb2 as _protocol
2829
except ImportError:
2930
print("ERROR: protocol_pb2.py not found in build directory")
3031
print("Solution: Rebuild with: .\\scripts\\build.ps1 -Release")
3132
sys.exit(1)
3233

34+
protocol = cast(Any, _protocol)
35+
Request = protocol.Request
36+
Response = protocol.Response
37+
Value = protocol.Value
38+
ValueType = protocol.ValueType
39+
3340

3441
def run_non_interacting_example():
3542
# Find provider executable
@@ -194,7 +201,8 @@ def run_non_interacting_example():
194201
traceback.print_exc()
195202
return False
196203
finally:
197-
provider.stdin.close()
204+
if provider.stdin is not None:
205+
provider.stdin.close()
198206
provider.terminate()
199207
provider.wait(timeout=2)
200208

examples/sim_mode/test_sim.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import sys
1616
import time
1717
from pathlib import Path
18+
from typing import Any, cast
1819

1920
# Add protocol_pb2 to path
2021
build_dir = Path(__file__).parent.parent.parent / "build"
@@ -25,12 +26,18 @@
2526
sys.path.insert(0, str(build_dir))
2627

2728
try:
28-
from protocol_pb2 import Request, Response, Value, ValueType
29+
import protocol_pb2 as _protocol
2930
except ImportError:
3031
print("ERROR: protocol_pb2.py not found in build directory")
3132
print("Solution: Rebuild with: .\\scripts\\build.ps1 -Release")
3233
sys.exit(1)
3334

35+
protocol = cast(Any, _protocol)
36+
Request = protocol.Request
37+
Response = protocol.Response
38+
Value = protocol.Value
39+
ValueType = protocol.ValueType
40+
3441

3542
def find_fluxgraph_server():
3643
"""Find FluxGraph server executable"""
@@ -110,7 +117,10 @@ def run_sim_example():
110117

111118
# Check if provider is still running
112119
if provider.poll() is not None:
113-
stderr_output = provider.stderr.read().decode()
120+
stderr_pipe = provider.stderr
121+
stderr_output = (
122+
stderr_pipe.read().decode() if stderr_pipe is not None else ""
123+
)
114124
print("[FAIL] Provider terminated unexpectedly:")
115125
print(stderr_output)
116126
return False
@@ -198,7 +208,8 @@ def run_sim_example():
198208
finally:
199209
# Cleanup
200210
try:
201-
provider.stdin.close()
211+
if provider.stdin is not None:
212+
provider.stdin.close()
202213
provider.terminate()
203214
provider.wait(timeout=2)
204215
except Exception:

mypy.ini

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[mypy]
2+
python_version = 3.12
3+
files = tests
4+
warn_unused_configs = True
5+
check_untyped_defs = True
6+
no_implicit_optional = True
7+
warn_redundant_casts = True
8+
warn_unused_ignores = True
9+
warn_return_any = True
10+
warn_unreachable = True
11+
strict_equality = True
12+
ignore_missing_imports = True

tests/support/proto_bootstrap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def load_protocol_module() -> tuple[ModuleType, Path]:
2323
add_build_dir_to_sys_path(build_dir)
2424

2525
try:
26-
import protocol_pb2 as protocol # type: ignore
26+
import protocol_pb2 as protocol
2727
except ImportError as exc:
2828
raise RuntimeError(
2929
f"protocol_pb2 module not found in {build_dir}.\n{_import_hint()}"

0 commit comments

Comments
 (0)