Skip to content

[Xpress] Remove deprecation warnings (#1)#3794

Open
XPRSc4v4 wants to merge 17 commits intoPyomo:mainfrom
XPRSc4v4:main
Open

[Xpress] Remove deprecation warnings (#1)#3794
XPRSc4v4 wants to merge 17 commits intoPyomo:mainfrom
XPRSc4v4:main

Conversation

@XPRSc4v4
Copy link

@XPRSc4v4 XPRSc4v4 commented Dec 5, 2025

Hi!

Fixes

  • Deprecated function names in Xpress 9.8+ (Python API v46)
  • Removed enums in Xpress 9.8+
  • Compatibility with both pre-9.8 and post-9.8 Xpress versions

Summary/Motivation:

Starting with Xpress 9.8 (Python API version 46), FICO deprecated lowercase function names in favor of camelCase (e.g., lpoptimizelpOptimize) and removed several enum types. The old functions are still available but deprecated, and will be removed in future releases. This PR adds runtime version detection to dispatch to the correct functions and enums based on the installed Xpress version, eliminating deprecation warnings while maintaining backward compatibility.

Changes proposed in this PR:

  • Extended version detection logic that checks Xpress Python API version at runtime
  • Created compatibility wrappers that dispatch to correct function names (lowercase for v45-, camelCase for v46+)
  • Updated enum handling to use new attribute access pattern for v46+ while maintaining old enum values for earlier versions
  • Modified tests to use XpressDirect interface instead of calling Xpress Python APIs directly
  • All changes maintain full backward compatibility with Xpress versions prior to 9.8

Legal Acknowledgement

By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the BSD license.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

* TXP-7757: removed most deprecation warnings up to current unpublished release

* Fixed more warnings

* Missing version agnostic functions

* Fixed version specific LPStatus enums + renamed get-lb/ub methods

* Suggested improvements
@XPRSc4v4 XPRSc4v4 changed the title Remove deprecation warnings (#1) [Xpress] Remove deprecation warnings (#1) Dec 5, 2025
@codecov
Copy link

codecov bot commented Dec 8, 2025

Codecov Report

❌ Patch coverage is 91.03448% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.47%. Comparing base (f2d23a5) to head (2121e59).

Files with missing lines Patch % Lines
pyomo/solvers/plugins/solvers/xpress_direct.py 90.84% 13 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3794      +/-   ##
==========================================
- Coverage   89.48%   89.47%   -0.01%     
==========================================
  Files         904      904              
  Lines      105385   105474      +89     
==========================================
+ Hits        94299    94377      +78     
- Misses      11086    11097      +11     
Flag Coverage Δ
builders 29.05% <36.55%> (+0.01%) ⬆️
default 83.57% <71.72%> (?)
expensive 35.54% <36.55%> (?)
linux 86.73% <57.24%> (-2.48%) ⬇️
linux_other 86.73% <57.24%> (-0.03%) ⬇️
oldsolvers 29.73% <56.55%> (+0.04%) ⬆️
osx 82.88% <57.24%> (-0.03%) ⬇️
win 84.96% <57.24%> (-0.05%) ⬇️
win_other 84.96% <57.24%> (-0.05%) ⬇️
xpress95 33.77% <37.24%> (-49.25%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

PYVER=$(echo "py${{matrix.python}}" | sed 's/\.//g')
echo "Installing for $PYVER"
for PKG in 'cplex>=12.10' docplex gurobi "$XPRESS" cyipopt pymumps scip; do
for PKG in 'cplex>=12.10' docplex gurobi "$XPRESS" 'xpress<9.3' cyipopt pymumps scip; do
Copy link
Member

Choose a reason for hiding this comment

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

This is changing the xpress version for every GHA job using conda to install Python packages which is not what I think you intended. During the dev call we talked about installing an older version of xpress on just one or two jobs to exercise the version-specific logic in the solver interface. I think you can do this by modifying the if-tree above that sets the XPRESS environment variable. There is already some special logic there for windows so maybe we use the linux conda job for this. I think you can just modify the else section on line 450 to something like:

if test "${{matrix.TARGET}}" == linux; then
    XPRESS='xpress<9.3'
else
    XPRESS='xpress'
fi

Copy link
Author

Choose a reason for hiding this comment

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

Sorry, I should have asked for clarification during the call!
I've applied the changes, targeting Python 3.10 so the latest Xpress release is still tested in the other jobs. Let me know if there are any other issues.

Copy link
Member

Choose a reason for hiding this comment

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

So turns out we can't use the Linux conda job to test an older version of Xpress because we can't get ANY version of Xpress to install in our Linux/conda GHA job. I tried both Python 3.11 and 3.12. They fail saying the environment can't be satisfied because intel-openmp can't be found in our conda channels. I modified the workflow to try using the win/3.10 and win/3.11 jobs instead.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you, Bethany. Let me know if there is anything I could do to help!

Copy link
Member

Choose a reason for hiding this comment

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

Our conda environments are fragile on GHA so I switched to using the linux/3.10 and linux/3.11 jobs for this which install Xpress using pip. I'll mark this discussion as resolved once I verify that the right versions of Xpress were installed.

@blnicho blnicho moved this from Todo to Review In Progress in Pyomo 6.10 Jan 22, 2026
@mrmundt mrmundt requested review from blnicho and mrmundt January 27, 2026 19:43
@blnicho
Copy link
Member

blnicho commented Feb 4, 2026

@XPRSc4v4 unfortunately, I don't think there is a way to test an "old enough" version of Xpress to cover the version-based if-tree in the interface using our GHA infrastructure. Asking for xpress<9.3 in the linux pip jobs did install an old version of Xpress but it was unusable because other packages required Numpy 2 which I think led to an inconsistent environment where Xpress was installed but not importable/available. Correct me if I'm wrong, but the first version of Xpress to support Numpy 2 was 9.6 which I think uses the same Python API as 9.8 and thus won't exercise a different portion of the if-tree. Given limited testing resources, I don't think it makes sense to pin one of our jobs to Numpy 1 just to get a sufficiently old version of Xpress.

If you agree with my assessment then I think we should revert the changes to the GHA workflow and accept the slight decrease in coverage.

@XPRSc4v4
Copy link
Author

XPRSc4v4 commented Feb 4, 2026

I agree, it would have been nice to have coverage for those compatibility branches, but not at the expense of complicating the test environment. The slight decrease in coverage is fine. Thanks for looking into this!

Removed conditional installation for older Xpress version.
Copy link
Member

@jsiirola jsiirola left a comment

Choose a reason for hiding this comment

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

Overall this seems OK. I do have one suggestion that might simplify things (wrap the Xpress model class instead of adding a bunch of private dynamic functions on the Pyomo solver interface):

ComponentMap.hasher.hashable(xpress.var, False)
ComponentMap.hasher.hashable(xp.var, False)

# Xpress 9.8 (46) adopted camelcase function naming, deprecating the old names
Copy link
Member

Choose a reason for hiding this comment

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

Instead of creating all these function pointers for both old and new Xpress, would it be simpler and more clear to create an Xpress45Problem wrapper class that would wrap an old-style problem instance and support both the old-style and new-style interfaces? Something like:

class Xpress45Problem:
    def __init__(self, prob):
        super().__setattr__(self, '_wrapped_problem', prob)

    def __getattr__(self, name):
        # The new API is camelCase, whereas the old interface was
        # all lowercase: try the new API and fall back on all lowercase:
        try:
            return getattr(self._wrapped_problem, name)
        except AttributeError:
            return getattr(self._wrapped_problem, name.lower())

    def __setattr__(self, name, val):
        return setattr(self._wrapped_problem, name, val)
        'setLogFile': 'setlogfile',
        'lpOptimize'

@blnicho
Copy link
Member

blnicho commented Feb 6, 2026

@XPRSc4v4 we added a new Jenkins build that tests the old Xpress interface so we can get the test coverage we wanted. Could you address the review comment from @jsiirola and then we can get this merged?

@blnicho blnicho removed this from Pyomo 6.10 Feb 11, 2026
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.

5 participants