Skip to content

Commit

Permalink
Merge branch 'main' into gurobi-sh-deprecation
Browse files Browse the repository at this point in the history
  • Loading branch information
mrmundt authored Nov 5, 2024
2 parents 6aeba60 + ad90ee2 commit fec1416
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
24 changes: 18 additions & 6 deletions pyomo/solvers/plugins/solvers/xpress_direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,24 @@ def __init__(self, **kwds):
def available(self, exception_flag=True):
"""True if the solver is available."""

if exception_flag and not xpress_available:
xpress.log_import_warning(logger=__name__)
raise ApplicationError(
"No Python bindings available for %s solver plugin" % (type(self),)
)
return bool(xpress_available)
if not xpress_available:
if exception_flag:
xpress.log_import_warning(logger=__name__)
raise ApplicationError(
"No Python bindings available for %s solver plugin" % (type(self),)
)
return False

# Check that there is a valid license
try:
xpress.init()
return True
except:
if exception_flag:
raise
return False
finally:
xpress.free()

def _apply_solver(self):
StaleFlagManager.mark_all_as_stale()
Expand Down
57 changes: 56 additions & 1 deletion pyomo/solvers/tests/checks/test_xpress_persistent.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
import logging

import pyomo.common.unittest as unittest
import pyomo.environ as pe
import pyomo.solvers.plugins.solvers.xpress_direct as xpd

from pyomo.common.log import LoggingIntercept
from pyomo.core.expr.taylor_series import taylor_series_expansion
from pyomo.solvers.plugins.solvers.xpress_direct import xpress_available
from pyomo.opt.results.solver import TerminationCondition, SolverStatus
from pyomo.solvers.plugins.solvers.xpress_persistent import XpressPersistent

xpress_available = pe.SolverFactory('xpress_persistent').available(False)


class TestXpressPersistent(unittest.TestCase):
Expand Down Expand Up @@ -329,3 +335,52 @@ def test_nonconvexqp_infeasible(self):
self.assertEqual(
results.solver.termination_condition, TerminationCondition.infeasible
)

def test_available(self):
class mock_xpress(object):
def __init__(self, importable, initable):
self._initable = initable
xpd.xpress_available = importable

def log_import_warning(self, logger):
logging.getLogger(logger).warning("import warning")

def init(self):
if not self._initable:
raise RuntimeError("init failed")

def free(self):
pass

orig = xpd.xpress, xpd.xpress_available
try:
_xpress_persistent = XpressPersistent
xpd.xpress = mock_xpress(True, True)
with LoggingIntercept() as LOG:
self.assertTrue(XpressPersistent().available(True))
self.assertTrue(XpressPersistent().available(False))
self.assertEqual(LOG.getvalue(), "")

xpd.xpress = mock_xpress(False, False)
with LoggingIntercept() as LOG:
self.assertFalse(XpressPersistent().available(False))
self.assertEqual(LOG.getvalue(), "")
with LoggingIntercept() as LOG:
with self.assertRaisesRegex(
xpd.ApplicationError,
"No Python bindings available for .*XpressPersistent.* "
"solver plugin",
):
XpressPersistent().available(True)
self.assertEqual(LOG.getvalue(), "import warning\n")

xpd.xpress = mock_xpress(True, False)
with LoggingIntercept() as LOG:
self.assertFalse(XpressPersistent().available(False))
self.assertEqual(LOG.getvalue(), "")
with LoggingIntercept() as LOG:
with self.assertRaisesRegex(RuntimeError, "init failed"):
XpressPersistent().available(True)
self.assertEqual(LOG.getvalue(), "")
finally:
xpd.xpress, xpd.xpress_available = orig

0 comments on commit fec1416

Please sign in to comment.