def testCreateBigIntSchema(self): name = os.path.join(self.tempdir, 'output1.shp') a_bigint = 10 ** 18 - 1 fieldname = 'abigint' kwargs = { 'driver': 'ESRI Shapefile', 'crs': 'EPSG:4326', 'schema': { 'geometry': 'Point', 'properties': [(fieldname, 'int:10')]}} if get_gdal_version_num() < calc_gdal_version_num(2, 0, 0): with self.assertRaises(OverflowError): with fiona.open(name, 'w', **kwargs) as dst: rec = {} rec['geometry'] = {'type': 'Point', 'coordinates': (0, 0)} rec['properties'] = {fieldname: a_bigint} dst.write(rec) else: with fiona.open(name, 'w', **kwargs) as dst: rec = {} rec['geometry'] = {'type': 'Point', 'coordinates': (0, 0)} rec['properties'] = {fieldname: a_bigint} dst.write(rec) with fiona.open(name) as src: if get_gdal_version_num() >= calc_gdal_version_num(2, 0, 0): first = next(iter(src)) self.assertEqual(first['properties'][fieldname], a_bigint)
def testCreateBigIntSchema(self): name = os.path.join(self.tempdir, 'output1.shp') a_bigint = 10**18 - 1 fieldname = 'abigint' kwargs = { 'driver': 'ESRI Shapefile', 'crs': 'EPSG:4326', 'schema': { 'geometry': 'Point', 'properties': [(fieldname, 'int:10')] } } if get_gdal_version_num() < calc_gdal_version_num(2, 0, 0): with self.assertRaises(OverflowError): with fiona.open(name, 'w', **kwargs) as dst: rec = {} rec['geometry'] = {'type': 'Point', 'coordinates': (0, 0)} rec['properties'] = {fieldname: a_bigint} dst.write(rec) else: with fiona.open(name, 'w', **kwargs) as dst: rec = {} rec['geometry'] = {'type': 'Point', 'coordinates': (0, 0)} rec['properties'] = {fieldname: a_bigint} dst.write(rec) with fiona.open(name) as src: if get_gdal_version_num() >= calc_gdal_version_num(2, 0, 0): first = next(iter(src)) self.assertEqual(first['properties'][fieldname], a_bigint)
def test_gpkg(self): if get_gdal_version_num() < calc_gdal_version_num(1, 11, 0): self.assertRaises(DriverError, fiona.open, 'tests/data/coutwildrnp.gpkg', 'r', driver="GPKG") else: with fiona.open('tests/data/coutwildrnp.gpkg', 'r', driver="GPKG") as c: self.assertEquals(len(c), 48)
def test_gpkg(self): schema = {'geometry': 'Point', 'properties': [('title', 'str')]} crs = { 'a': 6370997, 'lon_0': -100, 'y_0': 0, 'no_defs': True, 'proj': 'laea', 'x_0': 0, 'units': 'm', 'b': 6370997, 'lat_0': 45 } path = os.path.join(self.tempdir, 'foo.gpkg') if get_gdal_version_num() < calc_gdal_version_num(1, 11, 0): self.assertRaises(DriverError, fiona.open, path, 'w', driver='GPKG', schema=schema, crs=crs) else: with fiona.open(path, 'w', driver='GPKG', schema=schema, crs=crs) as c: c.writerecords([{ 'geometry': { 'type': 'Point', 'coordinates': [0.0, 0.0] }, 'properties': { 'title': 'One' } }]) c.writerecords([{ 'geometry': { 'type': 'Point', 'coordinates': [2.0, 3.0] }, 'properties': { 'title': 'Two' } }]) with fiona.open(path) as c: self.assertEquals(c.schema['geometry'], 'Point') self.assertEquals(len(c), 2)
def _check_schema_driver_support(self): """Check support for the schema against the driver See GH#572 for discussion. """ gdal_version_major = get_gdal_version_num() // 1000000 for field in self._schema["properties"]: field_type = field.split(":")[0] if self._driver == "ESRI Shapefile": if field_type == "datetime": raise DriverSupportError( "ESRI Shapefile does not support datetime fields") elif field_type == "time": raise DriverSupportError( "ESRI Shapefile does not support time fields") elif self._driver == "GPKG": if field_type == "time": raise DriverSupportError( "GPKG does not support time fields") elif gdal_version_major == 1: if field_type == "datetime": raise DriverSupportError( "GDAL 1.x GPKG driver does not support datetime fields" ) elif self._driver == "GeoJSON": if gdal_version_major == 1: if field_type == "date": warnings.warn( "GeoJSON driver in GDAL 1.x silently converts date to string in non-standard format" ) elif field_type == "datetime": warnings.warn( "GeoJSON driver in GDAL 1.x silently converts datetime to string in non-standard format" ) elif field_type == "time": warnings.warn( "GeoJSON driver in GDAL 1.x silently converts time to string" )
def test_gpkg(self): schema = {'geometry': 'Point', 'properties': [('title', 'str')]} crs = { 'a': 6370997, 'lon_0': -100, 'y_0': 0, 'no_defs': True, 'proj': 'laea', 'x_0': 0, 'units': 'm', 'b': 6370997, 'lat_0': 45} path = os.path.join(self.tempdir, 'foo.gpkg') if get_gdal_version_num() < calc_gdal_version_num(1, 11, 0): self.assertRaises(DriverError, fiona.open, path, 'w', driver='GPKG', schema=schema, crs=crs) else: with fiona.open(path, 'w', driver='GPKG', schema=schema, crs=crs) as c: c.writerecords([{ 'geometry': {'type': 'Point', 'coordinates': [0.0, 0.0]}, 'properties': {'title': 'One'}}]) c.writerecords([{ 'geometry': {'type': 'Point', 'coordinates': [2.0, 3.0]}, 'properties': {'title': 'Two'}}]) with fiona.open(path) as c: self.assertEquals(c.schema['geometry'], 'Point') self.assertEquals(len(c), 2)
def __init__(self, path, mode='r', driver=None, schema=None, crs=None, encoding=None, layer=None, vsi=None, archive=None, enabled_drivers=None, crs_wkt=None, **kwargs): """The required ``path`` is the absolute or relative path to a file, such as '/data/test_uk.shp'. In ``mode`` 'r', data can be read only. In ``mode`` 'a', data can be appended to a file. In ``mode`` 'w', data overwrites the existing contents of a file. In ``mode`` 'w', an OGR ``driver`` name and a ``schema`` are required. A Proj4 ``crs`` string is recommended. If both ``crs`` and ``crs_wkt`` keyword arguments are passed, the latter will trump the former. In 'w' mode, kwargs will be mapped to OGR layer creation options. """ if not isinstance(path, string_types): raise TypeError("invalid path: %r" % path) if not isinstance(mode, string_types) or mode not in ('r', 'w', 'a'): raise TypeError("invalid mode: %r" % mode) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: %r" % driver) if schema and not hasattr(schema, 'get'): raise TypeError("invalid schema: %r" % schema) if crs and not isinstance(crs, compat.DICT_TYPES + string_types): raise TypeError("invalid crs: %r" % crs) if crs_wkt and not isinstance(crs_wkt, string_types): raise TypeError("invalid crs_wkt: %r" % crs_wkt) if encoding and not isinstance(encoding, string_types): raise TypeError("invalid encoding: %r" % encoding) if layer and not isinstance(layer, tuple(list(string_types) + [int])): raise TypeError("invalid name: %r" % layer) if vsi: if not isinstance(vsi, string_types) or vsi not in ('zip', 'tar', 'gzip'): raise TypeError("invalid vsi: %r" % vsi) if archive and not isinstance(archive, string_types): raise TypeError("invalid archive: %r" % archive) # Check GDAL version against drivers if (driver == "GPKG" and get_gdal_version_num() < calc_gdal_version_num(1, 11, 0)): raise DriverError( "GPKG driver requires GDAL 1.11.0, fiona was compiled " "against: {}".format(get_gdal_release_name())) self.session = None self.iterator = None self._len = 0 self._bounds = None self._driver = None self._schema = None self._crs = None self._crs_wkt = None self.env = None self.enabled_drivers = enabled_drivers self.path = vsi_path(path, vsi, archive) if mode == 'w': if layer and not isinstance(layer, string_types): raise ValueError("in 'r' mode, layer names must be strings") if driver == 'GeoJSON': if layer is not None: raise ValueError("the GeoJSON format does not have layers") self.name = 'OgrGeoJSON' # TODO: raise ValueError as above for other single-layer formats. else: self.name = layer or os.path.basename( os.path.splitext(path)[0]) else: if layer in (0, None): self.name = 0 else: self.name = layer or os.path.basename( os.path.splitext(path)[0]) self.mode = mode if self.mode == 'w': if driver == 'Shapefile': driver = 'ESRI Shapefile' if not driver: raise DriverError("no driver") elif driver not in supported_drivers: raise DriverError("unsupported driver: %r" % driver) elif self.mode not in supported_drivers[driver]: raise DriverError("unsupported mode: %r" % self.mode) self._driver = driver if not schema: raise SchemaError("no schema") elif 'properties' not in schema: raise SchemaError("schema lacks: properties") elif 'geometry' not in schema: raise SchemaError("schema lacks: geometry") self._schema = schema if crs_wkt: self._crs_wkt = crs_wkt elif crs: if 'init' in crs or 'proj' in crs or 'epsg' in crs.lower(): self._crs = crs else: raise CRSError("crs lacks init or proj parameter") if driver_count == 0: # create a local manager and enter self.env = GDALEnv() else: self.env = GDALEnv() self.env.__enter__() self._driver = driver self.encoding = encoding try: if self.mode == 'r': self.session = Session() self.session.start(self) elif self.mode in ('a', 'w'): self.session = WritingSession() self.session.start(self, **kwargs) except IOError: self.session = None raise if self.session is not None: self.guard_driver_mode() if not self.encoding: self.encoding = self.session.get_fileencoding().lower()
def __init__(self, path, mode='r', driver=None, schema=None, crs=None, encoding=None, layer=None, vsi=None, archive=None, enabled_drivers=None, crs_wkt=None, ignore_fields=None, ignore_geometry=False, **kwargs): """The required ``path`` is the absolute or relative path to a file, such as '/data/test_uk.shp'. In ``mode`` 'r', data can be read only. In ``mode`` 'a', data can be appended to a file. In ``mode`` 'w', data overwrites the existing contents of a file. In ``mode`` 'w', an OGR ``driver`` name and a ``schema`` are required. A Proj4 ``crs`` string is recommended. If both ``crs`` and ``crs_wkt`` keyword arguments are passed, the latter will trump the former. In 'w' mode, kwargs will be mapped to OGR layer creation options. """ if not isinstance(path, string_types): raise TypeError("invalid path: %r" % path) if not isinstance(mode, string_types) or mode not in ('r', 'w', 'a'): raise TypeError("invalid mode: %r" % mode) if driver and not isinstance(driver, string_types): raise TypeError("invalid driver: %r" % driver) if schema and not hasattr(schema, 'get'): raise TypeError("invalid schema: %r" % schema) if crs and not isinstance(crs, compat.DICT_TYPES + string_types): raise TypeError("invalid crs: %r" % crs) if crs_wkt and not isinstance(crs_wkt, string_types): raise TypeError("invalid crs_wkt: %r" % crs_wkt) if encoding and not isinstance(encoding, string_types): raise TypeError("invalid encoding: %r" % encoding) if layer and not isinstance(layer, tuple(list(string_types) + [int])): raise TypeError("invalid name: %r" % layer) if vsi: if not isinstance(vsi, string_types) or not vfs.valid_vsi(vsi): raise TypeError("invalid vsi: %r" % vsi) if archive and not isinstance(archive, string_types): raise TypeError("invalid archive: %r" % archive) # Check GDAL version against drivers if (driver == "GPKG" and get_gdal_version_num() < calc_gdal_version_num(1, 11, 0)): raise DriverError( "GPKG driver requires GDAL 1.11.0, fiona was compiled " "against: {}".format(get_gdal_release_name())) self.session = None self.iterator = None self._len = 0 self._bounds = None self._driver = None self._schema = None self._crs = None self._crs_wkt = None self.env = None self.enabled_drivers = enabled_drivers self.ignore_fields = ignore_fields self.ignore_geometry = bool(ignore_geometry) self.path = vfs.vsi_path(path, vsi, archive) if mode == 'w': if layer and not isinstance(layer, string_types): raise ValueError("in 'w' mode, layer names must be strings") if driver == 'GeoJSON': if layer is not None: raise ValueError("the GeoJSON format does not have layers") self.name = 'OgrGeoJSON' # TODO: raise ValueError as above for other single-layer formats. else: self.name = layer or os.path.basename(os.path.splitext(path)[0]) else: if layer in (0, None): self.name = 0 else: self.name = layer or os.path.basename(os.path.splitext(path)[0]) self.mode = mode if self.mode == 'w': if driver == 'Shapefile': driver = 'ESRI Shapefile' if not driver: raise DriverError("no driver") elif driver not in supported_drivers: raise DriverError( "unsupported driver: %r" % driver) elif self.mode not in supported_drivers[driver]: raise DriverError( "unsupported mode: %r" % self.mode) self._driver = driver if not schema: raise SchemaError("no schema") elif 'properties' not in schema: raise SchemaError("schema lacks: properties") elif 'geometry' not in schema: raise SchemaError("schema lacks: geometry") self._schema = schema if crs_wkt: self._crs_wkt = crs_wkt elif crs: if 'init' in crs or 'proj' in crs or 'epsg' in crs.lower(): self._crs = crs else: raise CRSError("crs lacks init or proj parameter") if driver_count == 0: # create a local manager and enter self.env = AWSGDALEnv() else: self.env = AWSGDALEnv() self.env.__enter__() self._driver = driver kwargs.update(encoding=encoding or '') self.encoding = encoding try: if self.mode == 'r': self.session = Session() self.session.start(self, **kwargs) elif self.mode in ('a', 'w'): self.session = WritingSession() self.session.start(self, **kwargs) except IOError: self.session = None raise if self.session is not None: self.guard_driver_mode() if not self.encoding: self.encoding = self.session.get_fileencoding().lower() if self.mode in ("a", "w"): self._valid_geom_types = _get_valid_geom_types(self.schema, self.driver)
'schema': { 'geometry': 'BOGUS', 'properties': {}}} try: fiona.open(tmpfile, 'w', **profile) except UnsupportedGeometryTypeError: assert True @pytest.mark.parametrize('x', list(range(1, 10))) def test_normalize_int32(x): assert normalize_field_type('int:{}'.format(x)) == 'int32' @pytest.mark.skipif(get_gdal_version_num() < calc_gdal_version_num(2, 0, 0), reason="64-bit integer fields require GDAL 2+") @pytest.mark.parametrize('x', list(range(10, 20))) def test_normalize_int64(x): assert normalize_field_type('int:{}'.format(x)) == 'int64' @pytest.mark.parametrize('x', list(range(0, 20))) def test_normalize_str(x): assert normalize_field_type('str:{}'.format(x)) == 'str' def test_normalize_bool(): assert normalize_field_type('bool') == 'bool'
from fiona.ogrext import ( calc_gdal_version_num, get_gdal_version_num, get_gdal_release_name) import warnings # These modules are imported by fiona.ogrext, but are also import here to # help tools like cx_Freeze find them automatically from fiona import _geometry, _err, rfc3339 import uuid __all__ = ['bounds', 'listlayers', 'open', 'prop_type', 'prop_width'] __version__ = "1.6.4" __gdal_version__ = get_gdal_release_name().decode('utf-8') # Warn user that they use fiona 1.x with gdal 2.0 if get_gdal_version_num() >= calc_gdal_version_num(2, 0, 0): raise ImportError( "Fiona {0} is only compatible with GDAL 1.x (installed: {1})".format( __version__, __gdal_version__)) log = logging.getLogger('Fiona') class NullHandler(logging.Handler): def emit(self, record): pass log.addHandler(NullHandler()) def open( path, mode='r', driver=None, schema=None,