Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better import error #389

Merged
merged 13 commits into from
Mar 26, 2024
Merged

Better import error #389

merged 13 commits into from
Mar 26, 2024

Conversation

ewu63
Copy link
Collaborator

@ewu63 ewu63 commented Mar 17, 2024

Purpose

Closes #187

Expected time until merged

Few days

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (non-backwards-compatible fix or feature)
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no API changes)
  • Documentation update
  • Maintenance update
  • Other (please describe)

Testing

No new tests, no new change in behaviour other than ImportError is now raised instead of generic Error.

Checklist

  • I have run flake8 and black to make sure the Python code adheres to PEP-8 and is consistently formatted
  • I have formatted the Fortran code with fprettify or C/C++ code with clang-format as applicable
  • I have run unit and regression tests which pass locally with my changes
  • I have added new tests that prove my fix is effective or that my feature works
  • I have added necessary documentation

@ewu63 ewu63 requested a review from a team as a code owner March 17, 2024 04:46
Copy link

codecov bot commented Mar 17, 2024

Codecov Report

Attention: Patch coverage is 41.17647% with 40 lines in your changes are missing coverage. Please review.

Project coverage is 73.75%. Comparing base (cae6954) to head (cbfa664).

Files Patch % Lines
pyoptsparse/pyOpt_utils.py 66.66% 6 Missing ⚠️
pyoptsparse/pyIPOPT/pyIPOPT.py 16.66% 5 Missing ⚠️
pyoptsparse/pyNSGA2/pyNSGA2.py 16.66% 5 Missing ⚠️
pyoptsparse/pySNOPT/pySNOPT.py 16.66% 5 Missing ⚠️
pyoptsparse/pyCONMIN/pyCONMIN.py 20.00% 4 Missing ⚠️
pyoptsparse/pyNLPQLP/pyNLPQLP.py 20.00% 4 Missing ⚠️
pyoptsparse/pyPSQP/pyPSQP.py 20.00% 4 Missing ⚠️
pyoptsparse/pySLSQP/pySLSQP.py 20.00% 4 Missing ⚠️
pyoptsparse/pyALPSO/pyALPSO.py 0.00% 2 Missing ⚠️
pyoptsparse/pyParOpt/ParOpt.py 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #389      +/-   ##
==========================================
+ Coverage   73.35%   73.75%   +0.39%     
==========================================
  Files          22       22              
  Lines        3318     3296      -22     
==========================================
- Hits         2434     2431       -3     
+ Misses        884      865      -19     

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

marcomangano
marcomangano previously approved these changes Mar 21, 2024
Copy link
Contributor

@marcomangano marcomangano left a comment

Choose a reason for hiding this comment

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

LGTM, I only have one clarifying question below

import unittest

# isort: off
if sys.version_info[0] == 2:
Copy link
Contributor

Choose a reason for hiding this comment

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

wow, some py2 heritage here, good catch

if path is not None:
warnings.warn(
f"{module_name} module could not be imported from {path}.",
ImportWarning,
Copy link
Contributor

Choose a reason for hiding this comment

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

Not related directly to this PR, but is testflo raising ImportWarning by default? I tested just this function locally and the string above (which can be pretty useful) is not printed out by default - see here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm this is a good point. Maybe I will switch to UserWarning? I hate how a lot of warnings are not displayed by default.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, that's the default but we can set it explicitly.

marcomangano
marcomangano previously approved these changes Mar 22, 2024
module = str(e)
finally:
sys.path = orig_path
return module
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason why we delay throwing the ImportError? If we can't import the module, why not throw the error with the descriptive message here instead of a warning?

Do we need this "soft fail" type behavior somewhere that I missed? Otherwise I'm in favor of just throwing the ImportError here with the same message and only returning a module if the import is successful. But again, let me know if I missed something that makes this necessary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah it's because this is executed as part of the init process, and we don't necessarily want to raise an error. But if they try to instantiate the class and the compiled library is missing, we throw the error.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay that makes sense. I forgot that python tries to import anything that's involved in the init process. I'll approve this now.

if nlpqlp is None:
if raiseError:
raise Error("There was an error importing the compiled nlpqlp module")
if isinstance(nlpqlp, str) and raiseError:
Copy link
Contributor

Choose a reason for hiding this comment

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

Related to my other comment, why check for strings and then throw the same error that we could throw in the try_import_compiled_module_from_path function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is in the class init, so it's only executed when the class is instantiated.

@lamkina lamkina merged commit ab1618f into main Mar 26, 2024
11 of 12 checks passed
@lamkina lamkina deleted the better-import-error branch March 26, 2024 13:49
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.

Improve reporting of 3rd party library import errors
4 participants