Skip to content

Commit 71360af

Browse files
committed
Merge pull request #6104 from jreback/pytables_3.1
COMPAT: provide compat tests and better error messages for multiple file opening on PyTables >= 3.1 (GH6047)
2 parents d74bd31 + 3e849ee commit 71360af

File tree

2 files changed

+82
-44
lines changed

2 files changed

+82
-44
lines changed

pandas/io/pytables.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,12 @@ class DuplicateWarning(Warning):
211211
# oh the troubles to reduce import time
212212
_table_mod = None
213213
_table_supports_index = False
214-
214+
_table_file_open_policy_is_strict = False
215215

216216
def _tables():
217217
global _table_mod
218218
global _table_supports_index
219+
global _table_file_open_policy_is_strict
219220
if _table_mod is None:
220221
import tables
221222
from distutils.version import LooseVersion
@@ -225,8 +226,15 @@ def _tables():
225226
ver = tables.__version__
226227
_table_supports_index = LooseVersion(ver) >= '2.3'
227228

228-
return _table_mod
229+
# set the file open policy
230+
# return the file open policy; this changes as of pytables 3.1
231+
# depending on the HDF5 version
232+
try:
233+
_table_file_open_policy_is_strict = tables.file._FILE_OPEN_POLICY == 'strict'
234+
except:
235+
pass
229236

237+
return _table_mod
230238

231239
@contextmanager
232240
def get_store(path, **kwargs):
@@ -524,6 +532,22 @@ def open(self, mode='a', **kwargs):
524532
self._handle = tables.openFile(self._path, 'r', **kwargs)
525533
else:
526534
raise
535+
536+
except (ValueError) as e:
537+
538+
# trap PyTables >= 3.1 FILE_OPEN_POLICY exception
539+
# to provide an updated message
540+
if 'FILE_OPEN_POLICY' in str(e):
541+
542+
e = ValueError("PyTables [{version}] no longer supports opening multiple files\n"
543+
"even in read-only mode on this HDF5 version [{hdf_version}]. You can accept this\n"
544+
"and not open the same file multiple times at once,\n"
545+
"upgrade the HDF5 version, or downgrade to PyTables 3.0.0 which allows\n"
546+
"files to be opened multiple times at once\n".format(version=tables.__version__,
547+
hdf_version=tables.getHDF5Version()))
548+
549+
raise e
550+
527551
except (Exception) as e:
528552

529553
# trying to read from a non-existant file causes an error which

pandas/io/tests/test_pytables.py

+56-42
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
IncompatibilityWarning, PerformanceWarning,
1616
AttributeConflictWarning, DuplicateWarning,
1717
PossibleDataLossError, ClosedFileError)
18+
from pandas.io import pytables as pytables
1819
import pandas.util.testing as tm
1920
from pandas.util.testing import (assert_panel4d_equal,
2021
assert_panel_equal,
@@ -3683,53 +3684,66 @@ def test_multiple_open_close(self):
36833684
self.assert_('CLOSED' in str(store))
36843685
self.assert_(not store.is_open)
36853686

3686-
# multiples
3687-
store1 = HDFStore(path)
3688-
store2 = HDFStore(path)
3689-
3690-
self.assert_('CLOSED' not in str(store1))
3691-
self.assert_('CLOSED' not in str(store2))
3692-
self.assert_(store1.is_open)
3693-
self.assert_(store2.is_open)
3694-
3695-
store1.close()
3696-
self.assert_('CLOSED' in str(store1))
3697-
self.assert_(not store1.is_open)
3698-
self.assert_('CLOSED' not in str(store2))
3699-
self.assert_(store2.is_open)
3700-
3701-
store2.close()
3702-
self.assert_('CLOSED' in str(store1))
3703-
self.assert_('CLOSED' in str(store2))
3704-
self.assert_(not store1.is_open)
3705-
self.assert_(not store2.is_open)
3706-
3707-
# nested close
3708-
store = HDFStore(path,mode='w')
3709-
store.append('df',df)
3687+
with ensure_clean_path(self.path) as path:
37103688

3711-
store2 = HDFStore(path)
3712-
store2.append('df2',df)
3713-
store2.close()
3714-
self.assert_('CLOSED' in str(store2))
3715-
self.assert_(not store2.is_open)
3689+
if pytables._table_file_open_policy_is_strict:
37163690

3717-
store.close()
3718-
self.assert_('CLOSED' in str(store))
3719-
self.assert_(not store.is_open)
3691+
# multiples
3692+
store1 = HDFStore(path)
3693+
def f():
3694+
HDFStore(path)
3695+
self.assertRaises(ValueError, f)
3696+
store1.close()
37203697

3721-
# double closing
3722-
store = HDFStore(path,mode='w')
3723-
store.append('df', df)
3698+
else:
37243699

3725-
store2 = HDFStore(path)
3726-
store.close()
3727-
self.assert_('CLOSED' in str(store))
3728-
self.assert_(not store.is_open)
3700+
# multiples
3701+
store1 = HDFStore(path)
3702+
store2 = HDFStore(path)
3703+
3704+
self.assert_('CLOSED' not in str(store1))
3705+
self.assert_('CLOSED' not in str(store2))
3706+
self.assert_(store1.is_open)
3707+
self.assert_(store2.is_open)
3708+
3709+
store1.close()
3710+
self.assert_('CLOSED' in str(store1))
3711+
self.assert_(not store1.is_open)
3712+
self.assert_('CLOSED' not in str(store2))
3713+
self.assert_(store2.is_open)
3714+
3715+
store2.close()
3716+
self.assert_('CLOSED' in str(store1))
3717+
self.assert_('CLOSED' in str(store2))
3718+
self.assert_(not store1.is_open)
3719+
self.assert_(not store2.is_open)
3720+
3721+
# nested close
3722+
store = HDFStore(path,mode='w')
3723+
store.append('df',df)
3724+
3725+
store2 = HDFStore(path)
3726+
store2.append('df2',df)
3727+
store2.close()
3728+
self.assert_('CLOSED' in str(store2))
3729+
self.assert_(not store2.is_open)
3730+
3731+
store.close()
3732+
self.assert_('CLOSED' in str(store))
3733+
self.assert_(not store.is_open)
3734+
3735+
# double closing
3736+
store = HDFStore(path,mode='w')
3737+
store.append('df', df)
3738+
3739+
store2 = HDFStore(path)
3740+
store.close()
3741+
self.assert_('CLOSED' in str(store))
3742+
self.assert_(not store.is_open)
37293743

3730-
store2.close()
3731-
self.assert_('CLOSED' in str(store2))
3732-
self.assert_(not store2.is_open)
3744+
store2.close()
3745+
self.assert_('CLOSED' in str(store2))
3746+
self.assert_(not store2.is_open)
37333747

37343748
# ops on a closed store
37353749
with ensure_clean_path(self.path) as path:

0 commit comments

Comments
 (0)