From 5fc132394e175ba046d7c1ebf4c11ac5e0ca7485 Mon Sep 17 00:00:00 2001 From: jreback Date: Sun, 3 Nov 2013 12:18:26 -0500 Subject: [PATCH] TST: make pytables tests go thru a temporary dir and file TST/BUG: incorrect way of testing for r+ modes --- pandas/io/pytables.py | 20 ++++++++++++-------- pandas/io/tests/test_pytables.py | 17 ++++++++++++++--- pandas/util/testing.py | 7 ++++--- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 97dc8dcdec73a..d3d113eaddc45 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -225,11 +225,6 @@ def _tables(): return _table_mod -def h5_open(path, mode): - tables = _tables() - return tables.openFile(path, mode) - - @contextmanager def get_store(path, **kwargs): """ @@ -475,6 +470,8 @@ def open(self, mode='a'): mode : {'a', 'w', 'r', 'r+'}, default 'a' See HDFStore docstring or tables.openFile for info about modes """ + tables = _tables() + if self._mode != mode: # if we are chaning a write mode to read, ok @@ -501,13 +498,20 @@ def open(self, mode='a'): fletcher32=self._fletcher32) try: - self._handle = h5_open(self._path, self._mode) - except IOError as e: # pragma: no cover + self._handle = tables.openFile(self._path, self._mode) + except (IOError) as e: # pragma: no cover if 'can not be written' in str(e): print('Opening %s in read-only mode' % self._path) - self._handle = h5_open(self._path, 'r') + self._handle = tables.openFile(self._path, 'r') else: raise + except (Exception) as e: + + # trying to read from a non-existant file causes an error which + # is not part of IOError, make it one + if self._mode == 'r' and 'Unable to open/create file' in str(e): + raise IOError(str(e)) + raise def close(self): """ diff --git a/pandas/io/tests/test_pytables.py b/pandas/io/tests/test_pytables.py index 598f374e0fcf7..f51228fd89a42 100644 --- a/pandas/io/tests/test_pytables.py +++ b/pandas/io/tests/test_pytables.py @@ -3,6 +3,7 @@ import sys import os import warnings +import tempfile from contextlib import contextmanager import datetime @@ -57,6 +58,11 @@ def safe_close(store): @contextmanager def ensure_clean(path, mode='a', complevel=None, complib=None, fletcher32=False): + + # put in the temporary path if we don't have one already + if not len(os.path.dirname(path)): + path = tempfile.mkstemp(suffix=path)[1] + store = HDFStore(path, mode=mode, complevel=complevel, complib=complib, fletcher32=False) try: @@ -192,17 +198,22 @@ def test_api(self): with ensure_clean(self.path) as store: + path = store._path df = tm.makeDataFrame() + + _maybe_remove(store,'df') store.append('df',df.iloc[:10],append=True,format='table') store.append('df',df.iloc[10:],append=True,format='table') assert_frame_equal(read_hdf(path,'df'),df) # append to False + _maybe_remove(store,'df') store.append('df',df.iloc[:10],append=False,format='table') store.append('df',df.iloc[10:],append=True,format='table') assert_frame_equal(read_hdf(path,'df'),df) # formats + _maybe_remove(store,'df') store.append('df',df.iloc[:10],append=False,format='table') store.append('df',df.iloc[10:],append=True,format='table') assert_frame_equal(read_hdf(path,'df'),df) @@ -373,7 +384,7 @@ def check(mode): with tm.ensure_clean(self.path) as path: # constructor - if mode in ['r','r+']: + if mode in ['r']: self.assertRaises(IOError, HDFStore, path, mode=mode) else: @@ -384,7 +395,7 @@ def check(mode): with tm.ensure_clean(self.path) as path: # context - if mode in ['r','r+']: + if mode in ['r']: def f(): with get_store(path,mode=mode) as store: pass @@ -396,7 +407,7 @@ def f(): with tm.ensure_clean(self.path) as path: # conv write - if mode in ['r','r+']: + if mode in ['r']: self.assertRaises(IOError, df.to_hdf, path, 'df', mode=mode) df.to_hdf(path,'df',mode='w') else: diff --git a/pandas/util/testing.py b/pandas/util/testing.py index 2e4d1f3e8df74..414fb2ad1b77d 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -314,7 +314,7 @@ def ensure_clean(filename=None, return_filelike=False): filename : str (optional) if None, creates a temporary file which is then removed when out of scope. - return_filelike: bool (default False) + return_filelike : bool (default False) if True, returns a file-like which is *always* cleaned. Necessary for savefig and other functions which want to append extensions. Ignores filename if True. @@ -329,8 +329,9 @@ def ensure_clean(filename=None, return_filelike=False): else: # if we are not passed a filename, generate a temporary - if filename is None: - filename = tempfile.mkstemp()[1] + # make sure that we are using a temp dir as well + suffix = filename if filename is not None and not len(os.path.dirname(filename)) else '' + filename = tempfile.mkstemp(suffix=suffix)[1] try: yield filename