test_optional_dependency.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import sys
  2. import types
  3. import pytest
  4. from pandas.compat._optional import (
  5. VERSIONS,
  6. import_optional_dependency,
  7. )
  8. import pandas._testing as tm
  9. def test_import_optional():
  10. match = "Missing .*notapackage.* pip .* conda .* notapackage"
  11. with pytest.raises(ImportError, match=match) as exc_info:
  12. import_optional_dependency("notapackage")
  13. # The original exception should be there as context:
  14. assert isinstance(exc_info.value.__context__, ImportError)
  15. result = import_optional_dependency("notapackage", errors="ignore")
  16. assert result is None
  17. def test_xlrd_version_fallback():
  18. pytest.importorskip("xlrd")
  19. import_optional_dependency("xlrd")
  20. def test_bad_version(monkeypatch):
  21. name = "fakemodule"
  22. module = types.ModuleType(name)
  23. module.__version__ = "0.9.0"
  24. sys.modules[name] = module
  25. monkeypatch.setitem(VERSIONS, name, "1.0.0")
  26. match = "Pandas requires .*1.0.0.* of .fakemodule.*'0.9.0'"
  27. with pytest.raises(ImportError, match=match):
  28. import_optional_dependency("fakemodule")
  29. # Test min_version parameter
  30. result = import_optional_dependency("fakemodule", min_version="0.8")
  31. assert result is module
  32. with tm.assert_produces_warning(UserWarning):
  33. result = import_optional_dependency("fakemodule", errors="warn")
  34. assert result is None
  35. module.__version__ = "1.0.0" # exact match is OK
  36. result = import_optional_dependency("fakemodule")
  37. assert result is module
  38. with pytest.raises(ImportError, match="Pandas requires version '1.1.0'"):
  39. import_optional_dependency("fakemodule", min_version="1.1.0")
  40. with tm.assert_produces_warning(UserWarning):
  41. result = import_optional_dependency(
  42. "fakemodule", errors="warn", min_version="1.1.0"
  43. )
  44. assert result is None
  45. result = import_optional_dependency(
  46. "fakemodule", errors="ignore", min_version="1.1.0"
  47. )
  48. assert result is None
  49. def test_submodule(monkeypatch):
  50. # Create a fake module with a submodule
  51. name = "fakemodule"
  52. module = types.ModuleType(name)
  53. module.__version__ = "0.9.0"
  54. sys.modules[name] = module
  55. sub_name = "submodule"
  56. submodule = types.ModuleType(sub_name)
  57. setattr(module, sub_name, submodule)
  58. sys.modules[f"{name}.{sub_name}"] = submodule
  59. monkeypatch.setitem(VERSIONS, name, "1.0.0")
  60. match = "Pandas requires .*1.0.0.* of .fakemodule.*'0.9.0'"
  61. with pytest.raises(ImportError, match=match):
  62. import_optional_dependency("fakemodule.submodule")
  63. with tm.assert_produces_warning(UserWarning):
  64. result = import_optional_dependency("fakemodule.submodule", errors="warn")
  65. assert result is None
  66. module.__version__ = "1.0.0" # exact match is OK
  67. result = import_optional_dependency("fakemodule.submodule")
  68. assert result is submodule
  69. def test_no_version_raises(monkeypatch):
  70. name = "fakemodule"
  71. module = types.ModuleType(name)
  72. sys.modules[name] = module
  73. monkeypatch.setitem(VERSIONS, name, "1.0.0")
  74. with pytest.raises(ImportError, match="Can't determine .* fakemodule"):
  75. import_optional_dependency(name)