Skip to content

Fix implicit Optional annotations - #3529

Open
VenishPaneliya wants to merge 2 commits into
cvxpy:masterfrom
VenishPaneliya:implicit-optional
Open

VenishPaneliya wants to merge 2 commits into
cvxpy:masterfrom
VenishPaneliya:implicit-optional

Conversation

@VenishPaneliya

Copy link
Copy Markdown

Description

Four parameters annotate a concrete type but default to None, which PEP 484 prohibits. In each case None is a real, intended value, so only the annotation is wrong — annotation-only, no behaviour change.

ruff's rule for this fires on master and is clean afterwards:

$ ruff check --isolated --select RUF013 cvxpy/
cvxpy/problems/problem.py:958:24: RUF013 PEP 484 prohibits implicit `Optional`
cvxpy/reductions/solvers/conic_solvers/glop_conif.py:150:27: RUF013 ...
cvxpy/reductions/solvers/conic_solvers/pdlp_conif.py:143:27: RUF013 ...
cvxpy/reductions/solvers/conic_solvers/scip_conif.py:182:27: RUF013 ...
Found 4 errors.

Problem._solve(solver: str = None) — the body branches on if solver is not None: to decide whether to auto-select a solver, so None is the intended "not specified" value.

solve_via_data(solver_cache: dict = None) in GLOP, PDLP and SCIP — this one is a consistency outlier. Across the solver interfaces the same parameter appears 43 times as a plain, unannotated solver_cache=None, and elsewhere the code checks solver_cache is not None. Only these three added a dict annotation, and it excludes the None they default to.

I used | None to match the codebase (225 uses of | None, none of Optional[). Three of the four files don't have from __future__ import annotations, but with requires-python = ">=3.11", dict | None evaluates fine at runtime — I checked.

Issue link (if applicable): n/a

Type of change

  • New feature (backwards compatible)
  • New feature (breaking API changes)
  • Bug fix
  • Other (Documentation, CI, ...)

Contribution checklist

  • Add our license to new files. — no new files
  • Check that your code adheres to our coding style. — ruff check clean on all four files
  • Write unittests. — not applicable, annotation-only
  • Run the unittests and check that they're passing. — see note below
  • Run the benchmarks to make sure your change doesn't introduce a regression. — no runtime change

On tests: I couldn't run the suite locally — importing cvxpy from source needs the compiled extensions (it fails on qdldl in my environment). Since this only touches annotations, I verified the four modules compile and that the new annotations evaluate at runtime, and I'm relying on CI for the rest.

Four parameters annotate a concrete type but default to None, which
PEP 484 prohibits:

- Problem._solve takes `solver: str = None`; the body branches on
  `if solver is not None:` to decide whether to auto-select.
- GLOP, PDLP and SCIP's solve_via_data take `solver_cache: dict = None`.
  The other 43 solver interfaces leave the same parameter unannotated as
  `solver_cache=None`, and the codebase checks `solver_cache is not None`,
  so only these three introduced an annotation that excludes the None they
  default to.

Used `| None` to match the codebase, which uses it throughout and has no
`Optional[`. Annotation-only, no behaviour change.
@CLAassistant

CLAassistant commented Sep 14, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@PTNobel

PTNobel commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator
  1. Please sign the CLA
  2. If you are contributing compliance with a ruff rule, please enable the rule in pyproject.toml

Requested in review: the four annotation fixes in this PR bring the
package into compliance with ruff's RUF013, so enable the rule rather
than leaving it as a one-off cleanup. It complements UP007, which is
already enabled. 'ruff check .' passes across the repo with it on.
@VenishPaneliya

Copy link
Copy Markdown
Author

Thanks — done on point 2.

I've enabled the rule in pyproject.toml rather than leaving this as a one-off cleanup:

    "RUF013",  # Implicit Optional: PEP 484 prohibits `x: int = None`

It sits naturally alongside UP007, which is already enabled and is why | None is the house style here. ruff check . passes across the repo with it on, and I sanity-checked that the rule is genuinely live by temporarily reverting one of the four annotations — it fires as expected, then passes again once restored.

On point 1, the CLA: this one needs a browser sign-in on cla-assistant, which is on me to complete rather than something I can do from the PR. I'll get it signed and re-trigger the check.

This branch has not been deployed

No deployments
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.

3 participants