Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
77e0ee3
automatically run stub test
Joao-Dionisio Jan 14, 2026
ddf3d78
add isObjIntegral() for test
Joao-Dionisio Jan 14, 2026
e578db5
changelog
Joao-Dionisio Jan 14, 2026
1d7ed33
run on PR instead of pushes to master, and write a message
Joao-Dionisio Jan 14, 2026
6785f98
apply copilot suggestions
Joao-Dionisio Jan 14, 2026
292adf4
fix stub generator for numpy subclass overrides and Statistics types
Joao-Dionisio Jan 14, 2026
129eb2f
add type annotations to generated stub methods
Joao-Dionisio Jan 14, 2026
272d60b
add type annotations to __init__ and other special methods
Joao-Dionisio Jan 14, 2026
2eeedbb
fix auto-regeneration: add token, show diff in PR comment
Joao-Dionisio Jan 14, 2026
0a5ac24
restructure workflow: test -> regenerate -> test -> commit
Joao-Dionisio Jan 14, 2026
5645239
parse actual function parameters instead of using *args/**kwargs
Joao-Dionisio Jan 14, 2026
002afee
Add @disjoint_base decorator and fix sum() override for numpy subclasses
Joao-Dionisio Jan 14, 2026
75fdde8
Fix stubtest errors in stub generator
Joao-Dionisio Jan 14, 2026
746317c
Allow stub regeneration for forks when script is unchanged
Joao-Dionisio Jan 14, 2026
8cf8bc9
Only check script changes for fork PRs
Joao-Dionisio Jan 14, 2026
f36b628
Copy regenerated stub to installed location for stubtest
Joao-Dionisio Jan 14, 2026
490892e
Fix SIGPIPE error in commit step
Joao-Dionisio Jan 14, 2026
7ce6666
Auto-regenerate type stubs
github-actions[bot] Jan 14, 2026
3e22af9
Skip regeneration if stubtest already passes
Joao-Dionisio Jan 14, 2026
e67ee9a
Only import dataclass when needed
Joao-Dionisio Jan 14, 2026
6402c2d
Auto-fix some lint issues after stub regeneration
Joao-Dionisio Jan 14, 2026
e802f6f
Make lint job run after stubtest
Joao-Dionisio Jan 14, 2026
3e1ef48
Regenerate stubs without unused import
Joao-Dionisio Jan 14, 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
116 changes: 112 additions & 4 deletions .github/workflows/stubs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ jobs:
stubtest:
if: (github.event_name != 'pull_request') || (github.event.pull_request.draft == false)
runs-on: ubuntu-24.04
permissions:
contents: write
pull-requests: write
env:
PYTHON_VERSION: "3.14"

steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.head_ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0

- name: Install dependencies (SCIPOptSuite)
run: |
Expand All @@ -45,19 +53,119 @@ jobs:
export CFLAGS="-O0 -ggdb -Wall -Wextra -Werror -Wno-error=deprecated-declarations" # Debug mode. More warnings. Warnings as errors, but allow deprecated declarations.
python -m pip install . -v 2>&1 | tee build.log

- name: Run MyPy
- name: Run MyPy (before regeneration)
id: mypy_before
run: python -m mypy --package pyscipopt
continue-on-error: true

- name: Run stubtest (before regeneration)
id: stubtest_before
run: stubs/test.sh
continue-on-error: true

- name: Check if safe to run generate_stubs.py
id: check_script
run: |
# For same-repo PRs, always allow running the script
if [[ "${{ github.event.pull_request.head.repo.full_name }}" == "${{ github.repository }}" ]] || [[ "${{ github.event_name }}" != "pull_request" ]]; then
echo "allowed=true" >> $GITHUB_OUTPUT
echo "Same-repo PR or push - allowing regeneration"
else
# For fork PRs, only allow if script is unchanged from master
git fetch origin master
if git diff --quiet origin/master -- scripts/generate_stubs.py; then
echo "allowed=true" >> $GITHUB_OUTPUT
echo "Fork PR with unchanged script - allowing regeneration"
else
echo "allowed=false" >> $GITHUB_OUTPUT
echo "::warning::Fork PR with modified scripts/generate_stubs.py - skipping auto-regeneration for security"
fi
fi

- name: Regenerate stubs
if: steps.stubtest_before.outcome == 'failure' && steps.check_script.outputs.allowed == 'true'
run: |
python scripts/generate_stubs.py
# Auto-fix lint issues and format
pip install ruff
ruff check src/pyscipopt/scip.pyi --extend-select ANN,I,PYI,RUF100 --fix
ruff format src/pyscipopt/scip.pyi
# Copy regenerated stub to installed package location for stubtest
cp src/pyscipopt/scip.pyi "$(python -c 'import pyscipopt; print(pyscipopt.__path__[0])')/scip.pyi"

- name: Run MyPy (after regeneration)
if: steps.stubtest_before.outcome == 'failure' && steps.check_script.outputs.allowed == 'true'
run: python -m mypy --package pyscipopt

- name: Run stubtest
- name: Run stubtest (after regeneration)
if: steps.stubtest_before.outcome == 'failure' && steps.check_script.outputs.allowed == 'true'
run: stubs/test.sh

- name: Commit and push updated stubs
id: commit
if: steps.stubtest_before.outcome == 'failure' && github.event_name == 'pull_request' && steps.check_script.outputs.allowed == 'true' && github.event.pull_request.head.repo.full_name == github.repository
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add src/pyscipopt/scip.pyi

# Capture the diff for the PR comment
DIFF=$(git diff --cached --stat)
echo "diff<<EOF" >> $GITHUB_OUTPUT
echo "$DIFF" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Capture detailed changes (use || true to handle SIGPIPE from head)
DETAILED_DIFF=$(git diff --cached src/pyscipopt/scip.pyi | head -100 || true)
echo "detailed_diff<<EOF" >> $GITHUB_OUTPUT
echo "$DETAILED_DIFF" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

if git diff --cached --quiet; then
echo "committed=false" >> $GITHUB_OUTPUT
else
git commit -m "Auto-regenerate type stubs"
git push
echo "committed=true" >> $GITHUB_OUTPUT
fi

- name: Comment on PR
if: steps.commit.outputs.committed == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr comment ${{ github.event.pull_request.number }} --body "## 🤖 Type stubs automatically regenerated

The type stubs were out of date and have been automatically regenerated. A new commit has been pushed to this PR.

<details>
<summary>Changes summary</summary>

\`\`\`
${{ steps.commit.outputs.diff }}
\`\`\`

</details>

<details>
<summary>Detailed diff (first 100 lines)</summary>

\`\`\`diff
${{ steps.commit.outputs.detailed_diff }}
\`\`\`

</details>"

lint:
needs: stubtest
runs-on: ubuntu-latest
env:
FILES: src/pyscipopt/scip.pyi

steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.head_ref || github.ref }}

- name: Install Ruff
uses: astral-sh/ruff-action@v3
Expand All @@ -67,5 +175,5 @@ jobs:
- name: Lint type stubs
run: ruff check ${{ env.FILES }} --extend-select ANN,I,PYI,RUF100

- name: Format type stubs
run: ruff format ${{ env.FILES }}
- name: Format check type stubs
run: ruff format --check ${{ env.FILES }}
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- Added automated script for generating type stubs
- Include parameter names in type stubs
- Speed up MatrixExpr.sum(axis=...) via quicksum
- Run automated type stub generating script to PR pipeline
- Wrapped isObjIntegral() and test
### Fixed
- all fundamental callbacks now raise an error if not implemented
- Fixed the type of MatrixExpr.sum(axis=...) result from MatrixVariable to MatrixExpr.
Expand Down
Loading
Loading