Skip to content

Conversation

@jonathanberthias
Copy link
Contributor

@jonathanberthias jonathanberthias commented Dec 28, 2025

This PR adds a workflow that runs stubtest on the bundled type stubs. This means that whenever a class or method is added, the workflow will error until it is added to the scip.pyi file.

Part of #1072

Type errors

A pre-requisite to running stubtest is to have mypy type check the code without error. There were only a few errors reported by mypy which I don't think are controversial

Allow lists

For now, we rely on an allow list because the stubs are still wrong, they list all methods as taking *args, **kwargs parameters which isn't true at runtime. The allow list silences all the known current errors until we manually fix them.
There are 2 allow list files:

  • allowlist lists errors which are known and expected.
  • todo lists all the errors which we should aim to fix eventually.

Entries

Each entry is a regex matching the fully qualified name of the object with an error. Each line can thus hide multiple errors. For instance, for the entry pyscipopt.LP.addRow, these are the errors that get silenced:

error: pyscipopt.LP.addRow is inconsistent, stub does not have parameter "entries"
error: pyscipopt.LP.addRow is inconsistent, stub does not have parameter "lhs"
error: pyscipopt.LP.addRow is inconsistent, stub does not have parameter "rhs"
error: pyscipopt.LP.addRow is inconsistent, runtime does not have *args parameter "args"
error: pyscipopt.LP.addRow is inconsistent, runtime does not have **kwargs parameter "kwargs"

Conversely, some lines are actually duplicates. This is due to the re-exports. For instance, the entries:

pyscipopt.LP.addRow
pyscipopt.scip.LP.addRow

point to the same underlying object, so both entries could be removed at the same time.

Maintenance

Finally, the workflow will also fail if an entry in the allow list does not generate any error, ensuring the allow list is always up to date.

How to fix?

The way forward is to fix all the errors in the todo allow list. This means removing a couple of entries from the allow list, running stubs/test.sh and fixing any printed error.

Unfortunately I don't know any way to automate this part. stubtest detects the argument names but it has no idea what annotation they should have, so some human judgment is required. Or a massive token budget for a LLM 😉

stubs/test.sh Outdated

# Test the stubs for pyscipopt using stubtest
# This checks that the type hints in the stubs are consistent with the actual implementation
# Prerequisite: install mypy in same environment as pyscipopt and put stubtest in PATH
Copy link
Member

Choose a reason for hiding this comment

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

What would the error be when mypy is not installed? Also, can you be more explicit on what putting stubtest in PATH means?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What would the error be when mypy is not installed?

stubtest is distributed when you install mypy, so installing mypy is the only way to install stubtest.

Also, can you be more explicit on what putting stubtest in PATH means?

Yeah I agree that isn't clear, I just meant to activate the environment. Actually, I'll change the command to python -m stubtest, I think it's clearer

@Joao-Dionisio
Copy link
Member

There were only a few errors reported by mypy which I don't think are controversial

Are the mypy errors you ignored the ones you talk about later, or are they different? If so, can you please list (some of) them?

@jonathanberthias
Copy link
Contributor Author

Are the mypy errors you ignored the ones you talk about later, or are they different? If so, can you please list (some of) them?

No the mypy errors are the reason there are a few changes to the code outside the stubs folder, these are the errors on the current master that are now fixed:

.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:382: error: Signature of "__ge__" incompatible with supertype "numpy.ndarray"  [override]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:384: error: Signature of "__le__" incompatible with supertype "numpy.ndarray"  [override]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:397: error: Signature of "__ge__" incompatible with supertype "numpy.ndarray"  [override]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:398: error: Signature of "__le__" incompatible with supertype "numpy.ndarray"  [override]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:1303: error: Incompatible types in assignment (expression has type "None", variable has type "int")  [assignment]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:1304: error: Incompatible types in assignment (expression has type "None", variable has type "int")  [assignment]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:1306: error: Incompatible types in assignment (expression has type "None", variable has type "float")  [assignment]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:1307: error: Incompatible types in assignment (expression has type "None", variable has type "float")  [assignment]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:1308: error: Incompatible types in assignment (expression has type "None", variable has type "float")  [assignment]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:1309: error: Incompatible types in assignment (expression has type "None", variable has type "float")  [assignment]
.venv/lib/python3.14/site-packages/pyscipopt/scip.pyi:1310: error: Incompatible types in assignment (expression has type "None", variable has type "float")  [assignment]
.venv/lib/python3.14/site-packages/pyscipopt/__init__.py:7: error: Item "None" of "str | None" has no attribute "strip"  [union-attr]
.venv/lib/python3.14/site-packages/pyscipopt/recipes/getLocalConss.py:27: error: Need type annotation for "added_conss" (hint: "added_conss: list[<type>] = ...")  [var-annotated]
Found 13 errors in 3 files (checked 10 source files)

@codecov
Copy link

codecov bot commented Dec 28, 2025

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 55.07%. Comparing base (5ceac82) to head (944b204).

Files with missing lines Patch % Lines
src/pyscipopt/recipes/getLocalConss.py 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1141   +/-   ##
=======================================
  Coverage   55.07%   55.07%           
=======================================
  Files          24       24           
  Lines        5420     5420           
=======================================
  Hits         2985     2985           
  Misses       2435     2435           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants