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

importorskip variant that uses ModuleNotFoundError #11523

Closed
graingert opened this issue Oct 19, 2023 · 12 comments · Fixed by #12220 · May be fixed by #11524
Closed

importorskip variant that uses ModuleNotFoundError #11523

graingert opened this issue Oct 19, 2023 · 12 comments · Fixed by #12220 · May be fixed by #11524
Labels
good first issue easy issue that is friendly to new contributor type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature
Milestone

Comments

@graingert
Copy link
Member

What's the problem this feature will solve?

sometimes I install a package eg PyTables and it fails to compile properly and fails with an ImportError with an undefined symbol, however I don't see this in CI because I only do pytest.importorskip("pytables")

Describe the solution you'd like

a new kwarg to importorskip or a new function that catches ModuleNotFoundError instead of ImportError eg
importorskip(exc=ModuleNotFoundError) or findmoduleorskip(...)

Alternative Solutions

N/A

Additional context

Originally asked on discord

@nicoddemus
Copy link
Member

Hey @graingert thanks for the proposal.

a new kwarg to importorskip or a new function that catches ModuleNotFoundError instead of ImportError eg
importorskip(exc=ModuleNotFoundError) or findmoduleorskip(...)

I personally like importorskip(exc=ModuleNotFoundError) 👍

@nicoddemus nicoddemus added type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature good first issue easy issue that is friendly to new contributor labels Oct 19, 2023
graingert added a commit that referenced this issue Oct 19, 2023
@RonnyPfannschmidt
Copy link
Member

i think it would be very nice if a requirement could be passed to allow checking for versions

@bluetech
Copy link
Member

The alternative to exc= is to just narrow the current except ImportError to except ModuleNotFoundError. This will a breaking change, but I wonder if anyone really wants to skip on non-ModuleNotFoundError import errors?

@graingert
Copy link
Member Author

We could also check the exception message matches the module being imported

@nicoddemus
Copy link
Member

nicoddemus commented Oct 23, 2023

This will a breaking change, but I wonder if anyone really wants to skip on non-ModuleNotFoundError import errors?

Thought the same, I for one would always add exc=ModuleNotFoundError.

Perhaps it is worthwhile to go through a deprecation period, where we issue a warning in case a importorskip skipped a module but the message did not include the actual module name? Later we can apply the change to only catch ModuleNotFoundError then.

@The-Compiler
Copy link
Member

I don't understand the rationale of doing string matching against the exception message here. Why would we need to check that if we can just check the exception type? Why would it be useful to catch an ImportError which is not a ModuleNotFoundError but just happens to include the module name, vs. one which does not?

@nicoddemus
Copy link
Member

nicoddemus commented Oct 23, 2023

Why would we need to check that if we can just check the exception type? Why would it be useful to catch an ImportError which is not a ModuleNotFoundError but just happens to include the module name, vs. one which does not?

Just to issue a warning that the behavior will change in the future, where we will only catch ModuleNotFoundError:

except ModuleNotFoundError:
    skip()
except ImportError as e:
    if module_name not in str(e):
        warning(f"importorskip('{modulename}') caught an ImportError, but the message:\n{e}\n does not contain the module name. This behavior will change in the future to only catch ModuleNotFoundError")
   skip()

The idea is that we remove the except ImportError clause in a future release, as this is a breaking change (for the better IMHO).

@The-Compiler
Copy link
Member

I still don't follow. Why would we not want to warn if the message contains the module name?

@nicoddemus
Copy link
Member

To let users know that this might break their test suite in the future, suppose a user has this in their code base:

def test_numpy_support() -> None:
    pytest.importorskip("numpy")
    ...

Currently, the test is skipped, but not because numpy is not installed, but because it is failing to import due to something else entirely, for example due to an undefined symbol.

If we just change importorskip to catch ModuleNotFoundError, this would cause the test suite to break.

We might decide instead to introduce a warning, so users would see a warning like this currently:

PytestDeprecationWarning: importorskip caught ImportError with this message:

    ImportError: undefined symbol ...

Seems like the reason for the failure was not that the module was missing, but another cause.
pytest X will only catch `ModuleNotFoundError`, so this will fail in the future.

Then in a future release we change the code to only catch ModuleNotFoundError.


But now that I write this, perhaps does not make sense to introduce this warning at all? Seems like users would like for this to fail right away?

@The-Compiler
Copy link
Member

But in any case the module actually isn't present, we already will get a ModuleNotFoundError from Python. Why not warn on any ImportError, if anything? I don't see a reason why we should warn if, say, the undefined symbol in your example happens to be SomeLib::bla() but should not warn if the symbol happens to be called NumpyCExt::bla().

@nicoddemus
Copy link
Member

nicoddemus commented Oct 23, 2023

Oh you are right, we will already be catching ModuleNotFoundError explicitly, so any ImportError would be enough to generate a warning, no need to check the message at all.

Sorry for the noise!

We need to decide if we want to generate a warning, or go with the "breaking" change directly (I'm using quotes because one might argue that this is a clear improvement).

@nicoddemus
Copy link
Member

#12220 has been submitted, we need to decide if we will go with a standard improvement, or want to introduce a warning first.

@nicoddemus nicoddemus added this to the 8.2 milestone Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue easy issue that is friendly to new contributor type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature
Projects
None yet
5 participants