diff --git a/itertable/gis/mixins.py b/itertable/gis/mixins.py index aae1ec8..fb7fdfa 100644 --- a/itertable/gis/mixins.py +++ b/itertable/gis/mixins.py @@ -1,6 +1,7 @@ import fiona from shapely import wkt, geometry from ..loaders import FileLoader +from ..exceptions import LoadFailed from ..parsers.base import BaseParser from ..mappers import TupleMapper @@ -16,7 +17,22 @@ class FionaLoaderParser(FileLoader, BaseParser): def load(self): try: self.layers = fiona.listlayers(self.filename) - except (ValueError, IOError): + except OSError as e: + if self.require_existing: + raise LoadFailed( + e.strerror, + path=self.filename, + code=e.errno, + ) + else: + self.empty_file = True + except ValueError as e: + if self.require_existing: + raise LoadFailed(str(e)) + else: + self.empty_file = True + + if self.empty_file: driver = guess_driver(self.filename) self.meta = {'driver': driver} self.empty_file = True diff --git a/itertable/loaders.py b/itertable/loaders.py index 75dba4d..b69bbce 100644 --- a/itertable/loaders.py +++ b/itertable/loaders.py @@ -16,6 +16,7 @@ def load(self): class FileLoader(BaseLoader): filename = None + require_existing = True @property def read_mode(self): @@ -29,8 +30,14 @@ def load(self): try: self.file = open(self.filename, self.read_mode) self.empty_file = False - except IOError: - if self.binary: + except OSError as e: + if self.require_existing: + raise LoadFailed( + e.strerror, + path=self.filename, + code=e.errno, + ) + elif self.binary: self.file = BytesIO() else: self.file = StringIO() diff --git a/tests/files/nodata.csv b/tests/files/nodata.csv new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_gis.py b/tests/test_gis.py index 123409c..03de178 100644 --- a/tests/test_gis.py +++ b/tests/test_gis.py @@ -24,7 +24,9 @@ def test_shapeio_sync(self): source_file = self.get_filename("test", source_ext) dest_file = self.get_filename("sync", dest_ext, True) source_instance = ShapeIter(filename=source_file) - dest_instance = ShapeIter(filename=dest_file) + dest_instance = ShapeIter( + filename=dest_file, require_existing=False + ) source_instance.sync(dest_instance) self.check_instance(ShapeIter(filename=dest_file)) diff --git a/tests/test_load_file.py b/tests/test_load_file.py index cd51fe1..d4a5cec 100644 --- a/tests/test_load_file.py +++ b/tests/test_load_file.py @@ -1,5 +1,5 @@ from itertable import load_file -from itertable.exceptions import NoData +from itertable.exceptions import LoadFailed, NoData from .base import IterTestCase import pickle @@ -40,6 +40,19 @@ def test_load_nodata(self): instance[0] self.assertEqual(str(cm.exception), "No data returned!") + def test_load_non_existing(self): + filename = self.get_filename("nonexisting", "csv") + with self.assertRaises(LoadFailed) as cm: + load_file(filename) + self.assertEqual(str(cm.exception), "No such file or directory") + + def test_load_init_empty(self): + filename = self.get_filename("nonexisting", "csv") + instance = load_file(filename, options={'require_existing': False}) + with self.assertRaises(NoData) as cm: + instance[0] + self.assertEqual(str(cm.exception), "No data returned!") + def test_pickle(self): for ext in self.types: filename = self.get_filename("test", ext) diff --git a/tests/test_write.py b/tests/test_write.py index 7e46dcc..5f27851 100644 --- a/tests/test_write.py +++ b/tests/test_write.py @@ -35,6 +35,7 @@ def test_write_file(self): # Create an empty instance of the class instance = cls( filename=filename, + require_existing=False, field_names=['one', 'two', 'three'], # These only apply to XmlFileIter, will be ignored by others @@ -72,6 +73,7 @@ def duplicate(self, mode, xform): # Create empty instance of the destination Iter class dest_instance = dest_cls( filename=dest_file, + require_existing=False, field_names=['one', 'two', 'three'], root_tag="root", item_tag="item",