diff --git a/doc/source/install.rst b/doc/source/install.rst index 1c1f0c1d4cf8e..ee4b36f898e31 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -286,6 +286,7 @@ psycopg2 PostgreSQL engine for sqlalchemy pyarrow 0.9.0 Parquet and feather reading / writing pymysql MySQL engine for sqlalchemy pyreadstat SPSS files (.sav) reading +pytables 3.4.2 HDF5 reading / writing qtpy Clipboard I/O s3fs 0.0.8 Amazon S3 access xarray 0.8.2 pandas-like API for N-dimensional data diff --git a/pandas/compat/_optional.py b/pandas/compat/_optional.py index 4a7b8c4e88649..875edb3d3f1dd 100644 --- a/pandas/compat/_optional.py +++ b/pandas/compat/_optional.py @@ -19,6 +19,7 @@ "s3fs": "0.0.8", "scipy": "0.19.0", "sqlalchemy": "1.1.4", + "tables": "3.4.2", "xarray": "0.8.2", "xlrd": "1.1.0", "xlwt": "1.2.0", diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 983b1286eec91..79d6d8563a162 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -19,6 +19,7 @@ from pandas._libs import lib, writers as libwriters from pandas._libs.tslibs import timezones +from pandas.compat._optional import import_optional_dependency from pandas.errors import PerformanceWarning from pandas.core.dtypes.common import ( @@ -448,11 +449,7 @@ def __init__(self, path, mode=None, complevel=None, complib=None, if 'format' in kwargs: raise ValueError('format is not a defined argument for HDFStore') - try: - import tables # noqa - except ImportError as ex: # pragma: no cover - raise ImportError('HDFStore requires PyTables, "{ex!s}" problem ' - 'importing'.format(ex=ex)) + tables = import_optional_dependency("tables") if complib is not None and complib not in tables.filters.all_complibs: raise ValueError( diff --git a/pandas/tests/test_optional_dependency.py b/pandas/tests/test_optional_dependency.py index 3916bedb8e44b..74edc30f3e83d 100644 --- a/pandas/tests/test_optional_dependency.py +++ b/pandas/tests/test_optional_dependency.py @@ -4,7 +4,9 @@ import pytest from pandas.compat._optional import VERSIONS, import_optional_dependency +import pandas.util._test_decorators as td +import pandas as pd import pandas.util.testing as tm @@ -50,3 +52,11 @@ def test_no_version_raises(): with pytest.raises(ImportError, match="Can't determine .* fakemodule"): import_optional_dependency(name) + + +@td.skip_if_installed("tables") +def test_pytables_raises(): + df = pd.DataFrame({"A": [1, 2]}) + with pytest.raises(ImportError, match="tables"): + with tm.ensure_clean("foo.h5") as path: + df.to_hdf(path, "df") diff --git a/pandas/util/_test_decorators.py b/pandas/util/_test_decorators.py index 4cc316ffdd7ab..455d04458691b 100644 --- a/pandas/util/_test_decorators.py +++ b/pandas/util/_test_decorators.py @@ -99,6 +99,23 @@ def _skip_if_no_scipy(): safe_import('scipy.signal')) +def skip_if_installed( + package: str, +) -> MarkDecorator: + """ + Skip a test if a package is installed. + + Parameters + ---------- + package : str + The name of the package. + """ + return pytest.mark.skipif( + safe_import(package), + reason="Skipping because {} is installed.".format(package) + ) + + def skip_if_no( package: str, min_version: Optional[str] = None