Skip to content

Commit d65ce51

Browse files
Merge branch 'master' into remove-weakref-proxy
2 parents 5366af9 + b311726 commit d65ce51

9 files changed

Lines changed: 483 additions & 202 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,21 @@
22

33
## Unreleased
44
### Added
5+
- `Expr` and `GenExpr` support NumPy unary functions (`np.sin`, `np.cos`, `np.sqrt`, `np.exp`, `np.log`, `np.absolute`)
56
- Added `getBase()` and `setBase()` methods to `LP` class for getting/setting basis status
67
- Added `getMemUsed()`, `getMemTotal()`, and `getMemExternEstim()` methods
78
### Fixed
89
- Removed `Py_INCREF`/`Py_DECREF` on `Model` in `catchEvent`/`dropEvent` that caused memory leak for imbalanced usage
910
- Used `getIndex()` instead of `ptr()` for sorting nonlinear expression terms to avoid nondeterministic behavior
11+
- Fixed stubtest failures with mypy 1.20 by marking dunder method parameters as positional-only
12+
- Return `MatrixGenExpr` in `buildGenExprObj` instead of `MatrixExpr`
1013
- Plugins now hold strong references to their `Model` instead of `weakref.proxy`, fixing `ReferenceError` during cleanup callbacks (#1193)
1114
### Changed
1215
- Speed up `constant * Expr` via C-level API
16+
- Speed up `Term.__eq__` via the C-level API
1317
### Removed
1418
- Removed outdated warning about Make build system incompatibility
19+
- Removed `Term.ptrtuple` to optimize `Term` memory usage
1520

1621
## 6.1.0 - 2026.01.31
1722
### Added

scripts/generate_stubs.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ class StubGenerator:
4848

4949
# Special methods that need specific type hints
5050
COMPARISON_METHODS = {
51-
'__eq__': 'def __eq__(self, other: object) -> bool: ...',
52-
'__ne__': 'def __ne__(self, other: object) -> bool: ...',
53-
'__lt__': 'def __lt__(self, other: object) -> bool: ...',
54-
'__le__': 'def __le__(self, other: object) -> bool: ...',
55-
'__gt__': 'def __gt__(self, other: object) -> bool: ...',
56-
'__ge__': 'def __ge__(self, other: object) -> bool: ...',
51+
'__eq__': 'def __eq__(self, other: object, /) -> bool: ...',
52+
'__ne__': 'def __ne__(self, other: object, /) -> bool: ...',
53+
'__lt__': 'def __lt__(self, other: object, /) -> bool: ...',
54+
'__le__': 'def __le__(self, other: object, /) -> bool: ...',
55+
'__gt__': 'def __gt__(self, other: object, /) -> bool: ...',
56+
'__ge__': 'def __ge__(self, other: object, /) -> bool: ...',
5757
}
5858

5959
SPECIAL_METHODS = {
@@ -63,8 +63,8 @@ class StubGenerator:
6363
'__init__': 'def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: ...',
6464
'__repr__': 'def __repr__(self) -> str: ...',
6565
'__str__': 'def __str__(self) -> str: ...',
66-
'__delitem__': 'def __delitem__(self, key: Incomplete) -> None: ...',
67-
'__setitem__': 'def __setitem__(self, key: Incomplete, value: Incomplete) -> None: ...',
66+
'__delitem__': 'def __delitem__(self, key: Incomplete, /) -> None: ...',
67+
'__setitem__': 'def __setitem__(self, key: Incomplete, value: Incomplete, /) -> None: ...',
6868
}
6969

7070
# Methods that should NOT appear in stubs (internal Cython methods)
@@ -80,24 +80,24 @@ class StubGenerator:
8080

8181
# Methods with specific type hints (no *args, **kwargs)
8282
TYPED_METHODS = {
83-
'__getitem__': 'def __getitem__(self, index: Incomplete) -> Incomplete: ...',
83+
'__getitem__': 'def __getitem__(self, index: Incomplete, /) -> Incomplete: ...',
8484
'__iter__': 'def __iter__(self) -> Incomplete: ...',
8585
'__next__': 'def __next__(self) -> Incomplete: ...',
86-
'__add__': 'def __add__(self, other: Incomplete) -> Incomplete: ...',
87-
'__radd__': 'def __radd__(self, other: Incomplete) -> Incomplete: ...',
88-
'__sub__': 'def __sub__(self, other: Incomplete) -> Incomplete: ...',
89-
'__rsub__': 'def __rsub__(self, other: Incomplete) -> Incomplete: ...',
90-
'__mul__': 'def __mul__(self, other: Incomplete) -> Incomplete: ...',
91-
'__rmul__': 'def __rmul__(self, other: Incomplete) -> Incomplete: ...',
92-
'__truediv__': 'def __truediv__(self, other: Incomplete) -> Incomplete: ...',
93-
'__rtruediv__': 'def __rtruediv__(self, other: Incomplete) -> Incomplete: ...',
94-
'__rpow__': 'def __rpow__(self, other: Incomplete) -> Incomplete: ...',
86+
'__add__': 'def __add__(self, other: Incomplete, /) -> Incomplete: ...',
87+
'__radd__': 'def __radd__(self, other: Incomplete, /) -> Incomplete: ...',
88+
'__sub__': 'def __sub__(self, other: Incomplete, /) -> Incomplete: ...',
89+
'__rsub__': 'def __rsub__(self, other: Incomplete, /) -> Incomplete: ...',
90+
'__mul__': 'def __mul__(self, other: Incomplete, /) -> Incomplete: ...',
91+
'__rmul__': 'def __rmul__(self, other: Incomplete, /) -> Incomplete: ...',
92+
'__truediv__': 'def __truediv__(self, other: Incomplete, /) -> Incomplete: ...',
93+
'__rtruediv__': 'def __rtruediv__(self, other: Incomplete, /) -> Incomplete: ...',
94+
'__rpow__': 'def __rpow__(self, other: Incomplete, /) -> Incomplete: ...',
9595
'__neg__': 'def __neg__(self) -> Incomplete: ...',
9696
'__abs__': 'def __abs__(self) -> Incomplete: ...',
97-
'__iadd__': 'def __iadd__(self, other: Incomplete) -> Incomplete: ... # noqa: PYI034',
98-
'__isub__': 'def __isub__(self, other: Incomplete) -> Incomplete: ... # noqa: PYI034',
99-
'__imul__': 'def __imul__(self, other: Incomplete) -> Incomplete: ... # noqa: PYI034',
100-
'__matmul__': 'def __matmul__(self, other: Incomplete) -> Incomplete: ...',
97+
'__iadd__': 'def __iadd__(self, other: Incomplete, /) -> Incomplete: ... # noqa: PYI034',
98+
'__isub__': 'def __isub__(self, other: Incomplete, /) -> Incomplete: ... # noqa: PYI034',
99+
'__imul__': 'def __imul__(self, other: Incomplete, /) -> Incomplete: ... # noqa: PYI034',
100+
'__matmul__': 'def __matmul__(self, other: Incomplete, /) -> Incomplete: ...',
101101
'__array_ufunc__': 'def __array_ufunc__(self, ufunc: Incomplete, method: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: ...',
102102
}
103103

@@ -521,6 +521,11 @@ def _generate_method_stub(self, method_name: str, params: list, is_static: bool
521521
else:
522522
param_strs.append(f'{param_name}: Incomplete')
523523

524+
# Dunder methods (except __init__) have positional-only parameters
525+
is_dunder = method_name.startswith('__') and method_name.endswith('__')
526+
if is_dunder and method_name != '__init__' and not is_static:
527+
param_strs.append('/')
528+
524529
params_str = ', '.join(param_strs)
525530
return f'def {method_name}({params_str}) -> {return_type}: ...'
526531

0 commit comments

Comments
 (0)