Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
aecf12e
Improve baseline script
jonathanberthias Jun 28, 2026
cde7a12
Type var+1
jonathanberthias Jun 28, 2026
86bf99b
type var+constant
jonathanberthias Jun 28, 2026
d15fb5d
type var*constant
jonathanberthias Jun 28, 2026
70beeed
type prod_expr**2
jonathanberthias Jun 28, 2026
296f1e7
type abs(var)
jonathanberthias Jun 28, 2026
8ce164f
type var<=3
jonathanberthias Jun 28, 2026
7430116
type +var
jonathanberthias Jun 28, 2026
1559bb1
type -var
jonathanberthias Jun 28, 2026
53c0f98
type +mvar
jonathanberthias Jun 28, 2026
dc8b38a
type exp/log/sqrt/sin/cos
jonathanberthias Jun 28, 2026
a4688cd
type exp/log/sqrt/sin/cos as methods
jonathanberthias Jun 28, 2026
d8ad645
type comparison operators better
jonathanberthias Jun 28, 2026
a10b3e8
type binary operators better on Expr
jonathanberthias Jun 28, 2026
0144199
remove noise from GenExpr
jonathanberthias Jun 28, 2026
5376f57
remove noise from UnaryExpr
jonathanberthias Jun 28, 2026
611f320
Fix mypy errors
jonathanberthias Jun 28, 2026
0cf78d6
type MatrixExpr basic operations
jonathanberthias Jun 28, 2026
66d0a20
type abs(matrixexpr)
jonathanberthias Jun 28, 2026
68a3fde
type expr**int|float
jonathanberthias Jun 28, 2026
6661a85
type expr==float
jonathanberthias Jun 28, 2026
1934e05
type operations between expr and ndarray
jonathanberthias Jun 28, 2026
c57138e
type operations for matrixexpr
jonathanberthias Jun 28, 2026
9a144eb
type matrixexpr @
jonathanberthias Jun 28, 2026
330dc99
type matrixexpr ** float
jonathanberthias Jun 28, 2026
54be2af
type matrixexpr ** ndarray
jonathanberthias Jun 28, 2026
04aaf1c
type genexpr operations
jonathanberthias Jun 29, 2026
c1bdeb0
type constant**x
jonathanberthias Jun 29, 2026
bdaf349
Remove problematic rops for Expr
jonathanberthias Jun 29, 2026
3022baa
type genexpr**constant
jonathanberthias Jun 29, 2026
320818b
type comparisons for (Matrix)ExprCons
jonathanberthias Jun 29, 2026
c43b014
type most reverse binops
jonathanberthias Jun 29, 2026
908ac9c
Fix stubtest checks
jonathanberthias Jul 4, 2026
0396eb4
Remove Expr.__iadd__ stub
jonathanberthias Jul 4, 2026
a2ec9e9
Unpin ruff
jonathanberthias Jul 4, 2026
9a8f3eb
Review comments
jonathanberthias Jul 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/stubs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ jobs:
- name: Install Ruff
uses: astral-sh/ruff-action@v3
with:
version: "0.14.11"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the pin because this version was causing a weird formatting that was fixed in recent versions, but feel free to pin to a higher version if you want to keep a pinned version @Joao-Dionisio

args: "--version"

- name: Lint type stubs
Expand Down
195 changes: 145 additions & 50 deletions src/pyscipopt/scip.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ from typing import Any, AnyStr, ClassVar, Literal, SupportsFloat, Union, overloa

import numpy as np
from _typeshed import Incomplete
from typing_extensions import CapsuleType, disjoint_base
from typing_extensions import CapsuleType, Self, disjoint_base

CONST: Term
EventNames: dict
Expand All @@ -20,21 +20,37 @@ _core_dot: Incomplete
_core_dot_2d: Incomplete
_core_sum: Incomplete
buildGenExprObj: Incomplete
cos: Incomplete
exp: Incomplete
expr_to_array: Incomplete
expr_to_nodes: Incomplete
is_memory_freed: Incomplete
log: Incomplete
print_memory_in_use: Incomplete
quickprod: Incomplete
quicksum: Incomplete
readStatistics: Incomplete
sin: Incomplete
sqrt: Incomplete
str_conversion: Incomplete
value_to_array: Incomplete

@overload
def exp(x: float | Expr | GenExpr) -> UnaryExpr: ...
@overload
def exp(x: list | tuple | np.ndarray | MatrixExpr) -> MatrixGenExpr: ...
@overload
def log(x: float | Expr | GenExpr) -> UnaryExpr: ...
@overload
def log(x: list | tuple | np.ndarray | MatrixExpr) -> MatrixGenExpr: ...
@overload
def sqrt(x: float | Expr | GenExpr) -> UnaryExpr: ...
@overload
def sqrt(x: list | tuple | np.ndarray | MatrixExpr) -> MatrixGenExpr: ...
@overload
def sin(x: float | Expr | GenExpr) -> UnaryExpr: ...
@overload
def sin(x: list | tuple | np.ndarray | MatrixExpr) -> MatrixGenExpr: ...
@overload
def cos(x: float | Expr | GenExpr) -> UnaryExpr: ...
@overload
def cos(x: list | tuple | np.ndarray | MatrixExpr) -> MatrixGenExpr: ...

@disjoint_base
class Benders:
model: Incomplete
Expand Down Expand Up @@ -236,6 +252,9 @@ class Conshdlr:
class Constant(GenExpr):
number: Incomplete
def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: ...
def __pow__( # type: ignore[override]
self, other: float | Constant, mod: Incomplete = ..., /
) -> Constant: ...

@disjoint_base
class Constraint:
Expand Down Expand Up @@ -335,40 +354,75 @@ class ExprLike:
*args: Incomplete,
**kwargs: Incomplete,
) -> Incomplete: ...
def __radd__(self, other: object, /) -> Incomplete: ...
def __sub__(self, other: object, /) -> Incomplete: ...
def __rsub__(self, other: object, /) -> Incomplete: ...
def __rmul__(self, other: object, /) -> Incomplete: ...
def __rtruediv__(self, other: object, /) -> GenExpr: ...
def __neg__(self, /) -> Union[Expr, GenExpr]: ...
def __pos__(self, /) -> Union[Expr, GenExpr]: ...
def __abs__(self) -> GenExpr: ...
def exp(self) -> GenExpr: ...
def log(self) -> GenExpr: ...
def sqrt(self) -> GenExpr: ...
def sin(self) -> GenExpr: ...
def cos(self) -> GenExpr: ...
def __pos__(self, /) -> Self: ...
def __abs__(self, /) -> UnaryExpr: ...
def exp(self) -> UnaryExpr: ...
def log(self) -> UnaryExpr: ...
def sqrt(self) -> UnaryExpr: ...
def sin(self) -> UnaryExpr: ...
def cos(self) -> UnaryExpr: ...
@overload
def __le__(self, other: float | ExprLike, /) -> ExprCons: ...
@overload
def __le__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExprCons: ... # type: ignore[misc]
@overload
def __ge__(self, other: float | ExprLike, /) -> ExprCons: ...
@overload
def __ge__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExprCons: ... # type: ignore[misc]
@overload # type: ignore[override]
def __eq__(self, other: float | ExprLike, /) -> ExprCons: ...
@overload
def __eq__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExprCons: ...

@disjoint_base
class Expr(ExprLike):
terms: Incomplete
def __init__(self, terms: Incomplete = ...) -> None: ...
def degree(self) -> Incomplete: ...
def normalize(self) -> Incomplete: ...
def __add__(self, other: Incomplete, /) -> Incomplete: ...
def __eq__(self, other: object, /) -> bool: ...
def __ge__(self, other: object, /) -> bool: ...
def __neg__(self, /) -> Expr: ...
@overload
def __add__(self, other: float | Expr, /) -> Expr: ...
@overload
def __add__(self, other: GenExpr, /) -> SumExpr: ...
@overload
def __add__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __radd__(self, other: float, /) -> Expr: ...
@overload
def __sub__(self, other: float | Expr, /) -> Expr: ...
@overload
def __sub__(self, other: GenExpr, /) -> SumExpr: ...
@overload
def __sub__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __rsub__(self, other: float, /) -> Expr: ...
@overload
def __mul__(self, other: float | Expr, /) -> Expr: ...
@overload
def __mul__(self, other: GenExpr, /) -> ProdExpr: ...
@overload
def __mul__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __rmul__(self, other: float, /) -> Expr: ...
@overload
def __truediv__(self, other: float, /) -> Expr: ...
@overload
def __truediv__(self, other: Expr | GenExpr, /) -> ProdExpr: ...
@overload
def __truediv__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __rtruediv__(self, other: float, /) -> ProdExpr: ...
# __pow__'s return type depends on the value of `other`:
# non-negative integers (including integer-valued floats) yield Expr,
# negative integers and non-integers yield PowExpr
# We annotate the int case as Expr to handle the common case (e.g. x**2)
# knowing it might be wrong in some cases, and likewise the float case as
# PowExpr can be wrong. We aim to make the stubs useful in common cases
# even though the type system cannot fully express the real types.
@overload
def __pow__(self, other: int, mod: Incomplete = ..., /) -> Expr: ...
@overload
def __pow__(self, other: float, mod: Incomplete = ..., /) -> PowExpr: ...
def __rpow__(self, other: float, /) -> UnaryExpr: ...
def __getitem__(self, index: Incomplete, /) -> Incomplete: ...
def __gt__(self, other: object, /) -> bool: ...
def __iadd__(self, other: Incomplete, /) -> Incomplete: ... # noqa: PYI034
def __iter__(self) -> Incomplete: ...
def __le__(self, other: object, /) -> bool: ...
def __lt__(self, other: object, /) -> bool: ...
def __mul__(self, other: Incomplete, /) -> Incomplete: ...
def __ne__(self, other: object, /) -> bool: ...
def __pow__(self, other: Incomplete, modulo: Incomplete = ..., /) -> Incomplete: ...
def __rpow__(self, other: Incomplete, /) -> Incomplete: ...
def __truediv__(self, other: Incomplete, /) -> Incomplete: ...

@disjoint_base
class ExprCons:
Expand All @@ -380,12 +434,8 @@ class ExprCons:
) -> None: ...
def normalize(self) -> Incomplete: ...
def __bool__(self) -> bool: ...
def __eq__(self, other: object, /) -> bool: ...
def __ge__(self, other: object, /) -> bool: ...
def __gt__(self, other: object, /) -> bool: ...
def __le__(self, other: object, /) -> bool: ...
def __lt__(self, other: object, /) -> bool: ...
def __ne__(self, other: object, /) -> bool: ...
def __ge__(self, other: float, /) -> ExprCons: ...
def __le__(self, other: float, /) -> ExprCons: ...

@disjoint_base
class GenExpr(ExprLike):
Expand All @@ -394,17 +444,29 @@ class GenExpr(ExprLike):
def __init__(self) -> None: ...
def degree(self) -> Incomplete: ...
def getOp(self) -> Incomplete: ...
def __add__(self, other: Incomplete, /) -> Incomplete: ...
def __eq__(self, other: object, /) -> bool: ...
def __ge__(self, other: object, /) -> bool: ...
def __gt__(self, other: object, /) -> bool: ...
def __le__(self, other: object, /) -> bool: ...
def __lt__(self, other: object, /) -> bool: ...
def __mul__(self, other: Incomplete, /) -> Incomplete: ...
def __ne__(self, other: object, /) -> bool: ...
def __pow__(self, other: Incomplete, modulo: Incomplete = ..., /) -> Incomplete: ...
def __rpow__(self, other: Incomplete, /) -> Incomplete: ...
def __truediv__(self, other: Incomplete, /) -> Incomplete: ...
def __neg__(self, /) -> ProdExpr: ...
@overload
def __add__(self, other: float | ExprLike, /) -> SumExpr: ...
@overload
def __add__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __radd__(self, other: float, /) -> SumExpr: ...
@overload
def __sub__(self, other: float | ExprLike, /) -> SumExpr: ...
@overload
def __sub__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __rsub__(self, other: float, /) -> SumExpr: ...
@overload
def __mul__(self, other: float | ExprLike, /) -> ProdExpr: ...
@overload
def __mul__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __rmul__(self, other: float, /) -> ProdExpr: ...
@overload
def __truediv__(self, other: float | ExprLike, /) -> ProdExpr: ...
@overload
def __truediv__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ...
def __rtruediv__(self, other: float, /) -> ProdExpr: ...
def __pow__(self, other: float | Constant, mod: Incomplete = ..., /) -> PowExpr: ...
def __rpow__(self, other: float, mod: Incomplete = ..., /) -> UnaryExpr: ...

@disjoint_base
class Heur:
Expand Down Expand Up @@ -534,6 +596,38 @@ class MatrixExpr(np.ndarray):
*args: Incomplete,
**kwargs: Incomplete,
) -> Incomplete: ...
def __neg__(self, /) -> MatrixExpr: ...
def __abs__(self, /) -> MatrixExpr: ...
def __add__( # type: ignore[override]
self, other: float | ExprLike | np.ndarray | MatrixExpr, /
) -> MatrixExpr: ...
def __radd__(self, other: float, /) -> MatrixExpr: ... # type: ignore[override]
def __sub__( # type: ignore[override]
self, other: float | ExprLike | np.ndarray | MatrixExpr, /
) -> MatrixExpr: ...
def __rsub__(self, other: float, /) -> MatrixExpr: ... # type: ignore[override]
def __mul__( # type: ignore[override]
self, other: float | ExprLike | np.ndarray | MatrixExpr, /
) -> MatrixExpr: ...
def __rmul__(self, other: float, /) -> MatrixExpr: ... # type: ignore[override]
def __truediv__( # type: ignore[override]
self, other: float | ExprLike | np.ndarray | MatrixExpr, /
) -> MatrixExpr: ...
def __rtruediv__(self, other: float, /) -> MatrixExpr: ... # type: ignore[override]
def __eq__( # type: ignore[override]
self, other: float | ExprLike | np.ndarray | MatrixExpr, /
) -> MatrixExprCons: ...
def __le__( # type: ignore[override]
self, other: float | ExprLike | np.ndarray | MatrixExpr, /
) -> MatrixExprCons: ...
def __ge__( # type: ignore[override]
self, other: float | ExprLike | np.ndarray | MatrixExpr, /
) -> MatrixExprCons: ...
def __matmul__(self, other: np.ndarray | MatrixExpr, /) -> MatrixExpr: ... # type: ignore[override]
def __pow__( # type: ignore[override]
self, other: float | np.ndarray, mod: Incomplete = ..., /
) -> MatrixExpr: ...
def __rpow__(self, other: float, mod: Incomplete = ..., /) -> MatrixExpr: ... # type: ignore[override]

class MatrixExprCons(np.ndarray):
def __array_ufunc__(
Expand All @@ -543,7 +637,8 @@ class MatrixExprCons(np.ndarray):
*args: Incomplete,
**kwargs: Incomplete,
) -> Incomplete: ...
def __eq__(self, other: object, /) -> bool: ...
def __ge__(self, other: float | np.ndarray, /) -> MatrixExprCons: ... # type: ignore[override]
def __le__(self, other: float | np.ndarray, /) -> MatrixExprCons: ... # type: ignore[override]

class MatrixGenExpr(MatrixExpr): ...

Expand All @@ -562,6 +657,7 @@ class MatrixVariable(MatrixExpr):
def isInLP(self) -> Incomplete: ...
def varMayRound(self, direction: Incomplete = ...) -> Incomplete: ...
def vtype(self) -> Incomplete: ...
def __pos__(self, /) -> MatrixExpr: ... # type: ignore[override]

@disjoint_base
class Model:
Expand Down Expand Up @@ -2241,7 +2337,6 @@ class Term:

class UnaryExpr(GenExpr):
def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: ...
def __abs__(self) -> GenExpr: ...

@disjoint_base
class VarExpr(GenExpr):
Expand Down
6 changes: 6 additions & 0 deletions stubs/allowlist
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
.*.__reduce_cython__
.*.__setstate_cython__
pyscipopt.scip.__test__
# These exist at runtime but aren't useful in the stubs, they are added to the child classes
pyscipopt.scip.ExprLike.__radd__
pyscipopt.scip.ExprLike.__rmul__
pyscipopt.scip.ExprLike.__rsub__
pyscipopt.scip.ExprLike.__rtruediv__
pyscipopt.scip.ExprLike.__sub__
5 changes: 4 additions & 1 deletion stubs/baseline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ python "$REPO_ROOT"/scripts/generate_expr_type_tests.py
for test_file in "$REPO_ROOT"/tests/@types/*.py; do
echo "Updating mypy baseline for $test_file"
output_file="${test_file%.*}.mypy.out"
python -m mypy "$test_file" --warn-unused-ignores | grep "error:" > "$output_file"
# write to a temp file first to avoid truncating the output file if mypy fails
tmp=$(mktemp)
python -m mypy "$test_file" --warn-unused-ignores | grep "error:" > "$tmp"
mv "$tmp" "$output_file"
done
Loading
Loading