Skip to content

Commit ac1465a

Browse files
Run stubtest to check stubs are complete (#1141)
* Fix mypy errors * Generate stubtest allowlist * Split expected errors out of todo * Move all stub-related files to stubs folder * Add workflow to check stubs * Simplify file names * Don't run ruff on everything * Revert error added for testing * Clarify requirements for stubtest * Run mypy in CI
1 parent 5ceac82 commit ac1465a

File tree

7 files changed

+3777
-13
lines changed

7 files changed

+3777
-13
lines changed

.github/workflows/stubs.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Check type stubs
2+
env:
3+
version: 10.0.0
4+
5+
on:
6+
push:
7+
branches:
8+
- "master"
9+
pull_request:
10+
types: [opened, synchronize, reopened, ready_for_review]
11+
branches:
12+
- "master"
13+
workflow_dispatch:
14+
15+
defaults:
16+
run:
17+
shell: bash
18+
19+
jobs:
20+
stubtest:
21+
if: (github.event_name != 'pull_request') || (github.event.pull_request.draft == false)
22+
runs-on: ubuntu-24.04
23+
env:
24+
PYTHON_VERSION: "3.14"
25+
26+
steps:
27+
- uses: actions/checkout@v6
28+
29+
- name: Install dependencies (SCIPOptSuite)
30+
run: |
31+
wget --quiet --no-check-certificate "https://github.com/scipopt/scip/releases/download/v${{ env.version }}/scipoptsuite_${{ env.version }}-1+jammy_amd64.deb"
32+
sudo apt-get update && sudo apt install -y ./scipoptsuite_${{ env.version }}-1+jammy_amd64.deb
33+
34+
- name: Setup python ${{ env.PYTHON_VERSION }}
35+
uses: actions/setup-python@v4
36+
with:
37+
python-version: ${{ env.PYTHON_VERSION }}
38+
39+
- name: Install mypy
40+
run: |
41+
python -m pip install mypy
42+
43+
- name: Install PySCIPOpt
44+
run: |
45+
export CFLAGS="-O0 -ggdb -Wall -Wextra -Werror -Wno-error=deprecated-declarations" # Debug mode. More warnings. Warnings as errors, but allow deprecated declarations.
46+
python -m pip install . -v 2>&1 | tee build.log
47+
48+
- name: Run MyPy
49+
run: python -m mypy --package pyscipopt
50+
51+
- name: Run stubtest
52+
run: stubs/test.sh
53+
54+
lint:
55+
runs-on: ubuntu-latest
56+
env:
57+
FILES: src/pyscipopt/scip.pyi
58+
59+
steps:
60+
- uses: actions/checkout@v6
61+
62+
- name: Install Ruff
63+
uses: astral-sh/ruff-action@v3
64+
with:
65+
args: "--version"
66+
67+
- name: Lint type stubs
68+
run: ruff check ${{ env.FILES }} --extend-select PYI
69+
70+
- name: Format type stubs
71+
run: ruff format ${{ env.FILES }}

src/pyscipopt/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os
55
if hasattr(os, 'add_dll_directory'):
66
if os.getenv('SCIPOPTDIR'):
7-
os.add_dll_directory(os.path.join(os.getenv('SCIPOPTDIR').strip('"'), 'bin'))
7+
os.add_dll_directory(os.path.join(os.environ['SCIPOPTDIR'].strip('"'), 'bin'))
88

99
# export user-relevant objects:
1010
from pyscipopt.Multidict import multidict as multidict

src/pyscipopt/recipes/getLocalConss.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def getLocalConss(model: Model, node = None) -> List[List[Constraint]]:
2424
else:
2525
cur_node = node
2626

27-
added_conss = []
27+
added_conss: List[Constraint] = []
2828
while cur_node is not None:
2929
added_conss = cur_node.getAddedConss() + added_conss
3030
cur_node = cur_node.getParent()

src/pyscipopt/scip.pyi

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,9 @@ class MatrixExpr(numpy.ndarray):
379379
def sum(self, *args, **kwargs): ...
380380
def __add__(self, other): ...
381381
def __eq__(self, other: object) -> bool: ...
382-
def __ge__(self, other: object) -> bool: ...
382+
def __ge__(self, other: object) -> MatrixExprCons: ...
383383
def __iadd__(self, other): ...
384-
def __le__(self, other: object) -> bool: ...
384+
def __le__(self, other: object) -> MatrixExprCons: ...
385385
def __matmul__(self, *args, **kwargs): ...
386386
def __mul__(self, other): ...
387387
def __pow__(self, other): ...
@@ -394,8 +394,8 @@ class MatrixExpr(numpy.ndarray):
394394

395395
class MatrixExprCons(numpy.ndarray):
396396
def __eq__(self, other: object) -> bool: ...
397-
def __ge__(self, other: object) -> bool: ...
398-
def __le__(self, other: object) -> bool: ...
397+
def __ge__(self, other: object) -> MatrixExprCons: ...
398+
def __le__(self, other: object) -> MatrixExprCons: ...
399399

400400
class MatrixGenExpr(MatrixExpr): ...
401401

@@ -1300,14 +1300,14 @@ class Statistics:
13001300
copying_time: float
13011301
problem_name: str
13021302
presolved_problem_name: str
1303-
n_runs: int = None
1304-
n_nodes: int = None
1303+
n_runs: int | None = None
1304+
n_nodes: int | None = None
13051305
n_solutions_found: int = -1
1306-
first_solution: float = None
1307-
primal_bound: float = None
1308-
dual_bound: float = None
1309-
gap: float = None
1310-
primal_dual_integral: float = None
1306+
first_solution: float | None = None
1307+
primal_bound: float | None = None
1308+
dual_bound: float | None = None
1309+
gap: float | None = None
1310+
primal_dual_integral: float | None = None
13111311
@property
13121312
def n_binary_vars(self): ...
13131313
@property

stubs/allowlist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.*.__reduce_cython__
2+
.*.__setstate_cython__
3+
pyscipopt.scip.__test__

stubs/test.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash -e
2+
3+
# Test the stubs for pyscipopt using stubtest
4+
# This checks that the type hints in the stubs are consistent with the actual implementation
5+
# Prerequisite: install mypy (which provides stubtest) in the same environment as pyscipopt
6+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7+
python -m mypy.stubtest \
8+
--allowlist "$SCRIPT_DIR/allowlist" \
9+
--allowlist "$SCRIPT_DIR/todo" \
10+
pyscipopt

0 commit comments

Comments
 (0)