Merge branch 'importorskip-ModuleNotFoundError'

This commit is contained in:
shekhuverma 2024-04-19 19:27:12 +05:30
commit 1456b71990
3 changed files with 34 additions and 23 deletions

View File

@ -0,0 +1 @@
pytest.importorskip will now skip both ImportError and ModuleNotFoundError.

View File

@ -11,6 +11,8 @@ from typing import Protocol
from typing import Type
from typing import TypeVar
from .warning_types import PytestDeprecationWarning
class OutcomeException(BaseException):
"""OutcomeException and its subclass instances indicate and contain info
@ -192,7 +194,10 @@ def xfail(reason: str = "") -> NoReturn:
def importorskip(
modname: str, minversion: Optional[str] = None, reason: Optional[str] = None
modname: str,
minversion: Optional[str] = None,
reason: Optional[str] = None,
exc_type: Optional[Type[ImportError]] = None,
) -> Any:
"""Import and return the requested module ``modname``, or skip the
current test if the module cannot be imported.
@ -205,6 +210,8 @@ def importorskip(
:param reason:
If given, this reason is shown as the message when the module cannot
be imported.
:param exc_type:
If given, modules are skipped if this exception is raised.
:returns:
The imported module. This should be assigned to its canonical name.
@ -223,12 +230,24 @@ def importorskip(
# of existing directories with the same name we're trying to
# import but without a __init__.py file.
warnings.simplefilter("ignore")
if exc_type is None:
exc_type = ModuleNotFoundError
else:
exc_type = ImportError
warnings.warn(
PytestDeprecationWarning(
"The Default behaviour will change to ImportError in future",
)
)
try:
__import__(modname)
except ModuleNotFoundError as exc:
except exc_type as exc:
if reason is None:
reason = f"could not import {modname!r}: {exc}"
raise Skipped(reason, allow_module_level=True) from None
mod = sys.modules[modname]
if minversion is None:
return mod

View File

@ -1,5 +1,4 @@
# mypy: allow-untyped-defs
import builtins
from functools import partial
import inspect
import os
@ -8,8 +7,6 @@ import sys
import types
from typing import Dict
from typing import List
from typing import Mapping
from typing import Sequence
from typing import Tuple
from typing import Type
@ -22,6 +19,7 @@ from _pytest.config import ExitCode
from _pytest.monkeypatch import MonkeyPatch
from _pytest.outcomes import OutcomeException
from _pytest.pytester import Pytester
from _pytest.warning_types import PytestDeprecationWarning
import pytest
@ -765,25 +763,18 @@ def test_importorskip_imports_last_module_part() -> None:
assert os.path == ospath
def test_importorskip_importError_Exception() -> None:
## Mocking the import function to raise a importError
realimport = builtins.__import__
def test_importorskip_importError_warning(pytester: Pytester) -> None:
"""
importorskip() will only skip modules by ImportError as well as ModuleNotFoundError
will give warning when using ImportError
#11523
"""
fn = pytester.makepyfile("raise ImportError('some specific problem')")
pytester.syspathinsert()
def myimport(
name: str,
globals: Mapping[str, object] | None = None,
locals: Mapping[str, object] | None = None,
fromlist: Sequence[str] = (),
level: int = 0,
) -> types.ModuleType:
raise ImportError
builtins.__import__ = myimport
with pytest.raises(ImportError):
pytest.importorskip("abcdefghi")
builtins.__import__ = realimport
with pytest.raises(pytest.skip.Exception):
with pytest.warns(PytestDeprecationWarning):
pytest.importorskip(fn.stem, exc_type=ImportError)
def test_importorskip_dev_module(monkeypatch) -> None: