From 0b1c5e1efa6c5f6a35130de25f4ce5d602746143 Mon Sep 17 00:00:00 2001 From: William Zijie Zhang Date: Wed, 4 Mar 2026 15:41:41 -0500 Subject: [PATCH 1/4] Centralize sparsediffpy import into _bindings.py Move the duplicated try/except import of sparsediffpy from c_problem.py and converters.py into a single _bindings.py module. Co-Authored-By: Claude Opus 4.6 --- .../nlp_solvers/diff_engine/_bindings.py | 25 +++++++++++++++++++ .../nlp_solvers/diff_engine/c_problem.py | 9 +------ .../nlp_solvers/diff_engine/converters.py | 8 +----- 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py new file mode 100644 index 0000000000..1c31547c7f --- /dev/null +++ b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py @@ -0,0 +1,25 @@ +"""Centralized import for the sparsediffpy C bindings. + +Copyright 2025, the CVXPY developers + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +try: + from sparsediffpy import _sparsediffengine as _diffengine +except ImportError as e: + raise ImportError( + "NLP support requires sparsediffpy. Install with: pip install sparsediffpy" + ) from e + +__all__ = ["_diffengine"] diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py index 98daad1369..a6cfe9a366 100644 --- a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py +++ b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py @@ -19,14 +19,7 @@ import cvxpy as cp -# Import the low-level C bindings -try: - from sparsediffpy import _sparsediffengine as _diffengine -except ImportError as e: - raise ImportError( - "NLP support requires sparsediffpy. Install with: pip install sparsediffpy" - ) from e - +from cvxpy.reductions.solvers.nlp_solvers.diff_engine._bindings import _diffengine from cvxpy.reductions.solvers.nlp_solvers.diff_engine.converters import ( build_variable_dict, convert_expr, diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py index f56272a42d..03d2b6a0f1 100644 --- a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py +++ b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py @@ -25,13 +25,7 @@ import cvxpy as cp from cvxpy.reductions.inverse_data import InverseData -# Import the low-level C bindings -try: - from sparsediffpy import _sparsediffengine as _diffengine -except ImportError as e: - raise ImportError( - "NLP support requires sparsediffpy. Install with: pip install sparsediffpy" - ) from e +from cvxpy.reductions.solvers.nlp_solvers.diff_engine._bindings import _diffengine def normalize_shape(shape): From 5e207160cd8cc7d1199fedd0ce03900c0300ba7b Mon Sep 17 00:00:00 2001 From: William Zijie Zhang Date: Wed, 4 Mar 2026 16:21:53 -0500 Subject: [PATCH 2/4] cleanup fix --- .../nlp_solvers/diff_engine/_bindings.py | 25 ------------------- .../nlp_solvers/diff_engine/c_problem.py | 2 +- .../nlp_solvers/diff_engine/converters.py | 2 +- 3 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py deleted file mode 100644 index 1c31547c7f..0000000000 --- a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/_bindings.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Centralized import for the sparsediffpy C bindings. - -Copyright 2025, the CVXPY developers - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -try: - from sparsediffpy import _sparsediffengine as _diffengine -except ImportError as e: - raise ImportError( - "NLP support requires sparsediffpy. Install with: pip install sparsediffpy" - ) from e - -__all__ = ["_diffengine"] diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py index a6cfe9a366..a9e0f072ee 100644 --- a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py +++ b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py @@ -19,7 +19,7 @@ import cvxpy as cp -from cvxpy.reductions.solvers.nlp_solvers.diff_engine._bindings import _diffengine +from sparsediffpy import _sparsediffengine as _diffengine from cvxpy.reductions.solvers.nlp_solvers.diff_engine.converters import ( build_variable_dict, convert_expr, diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py index 03d2b6a0f1..e4e95838cc 100644 --- a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py +++ b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py @@ -25,7 +25,7 @@ import cvxpy as cp from cvxpy.reductions.inverse_data import InverseData -from cvxpy.reductions.solvers.nlp_solvers.diff_engine._bindings import _diffengine +from sparsediffpy import _sparsediffengine as _diffengine def normalize_shape(shape): From ece0fbbb4c42e672bb9277d33e0e709a5051afb8 Mon Sep 17 00:00:00 2001 From: William Zijie Zhang Date: Wed, 4 Mar 2026 16:56:48 -0500 Subject: [PATCH 3/4] fix import issue --- cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py index e4e95838cc..8468281187 100644 --- a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py +++ b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/converters.py @@ -21,12 +21,11 @@ import numpy as np from scipy import sparse +from sparsediffpy import _sparsediffengine as _diffengine import cvxpy as cp from cvxpy.reductions.inverse_data import InverseData -from sparsediffpy import _sparsediffengine as _diffengine - def normalize_shape(shape): """Normalize shape to 2D (d1, d2) for the C engine.""" From 9e919106166ee1310bb7f305a20f4cc361f400c2 Mon Sep 17 00:00:00 2001 From: William Zijie Zhang Date: Wed, 4 Mar 2026 17:01:51 -0500 Subject: [PATCH 4/4] fix import for c_problem as well --- cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py index a9e0f072ee..c9a922438b 100644 --- a/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py +++ b/cvxpy/reductions/solvers/nlp_solvers/diff_engine/c_problem.py @@ -16,10 +16,9 @@ """ import numpy as np +from sparsediffpy import _sparsediffengine as _diffengine import cvxpy as cp - -from sparsediffpy import _sparsediffengine as _diffengine from cvxpy.reductions.solvers.nlp_solvers.diff_engine.converters import ( build_variable_dict, convert_expr,