Esempio n. 1
0
def test_write_does_not_work_when_gdal_smaller_mingdal(tmpdir, driver,
                                                       testdata_generator,
                                                       monkeypatch):
    """
        Test if driver really can't write for gdal < driver_mode_mingdal

        If this test fails, it should be considered to update driver_mode_mingdal in drvsupport.py.

    """

    if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
        pytest.skip("BNA driver segfaults with gdal 1.11")
    if (driver == 'FlatGeobuf' and calc_gdal_version_num(3, 1, 0) <=
            get_gdal_version_num() < calc_gdal_version_num(3, 1, 3)):
        pytest.skip("See https://github.com/Toblerity/Fiona/pull/924")

    schema, crs, records1, _, test_equal, create_kwargs = testdata_generator(
        driver, range(0, 10), [])
    path = str(tmpdir.join(get_temp_filename(driver)))

    if (driver in driver_mode_mingdal['w'] and get_gdal_version_num() <
            calc_gdal_version_num(*driver_mode_mingdal['w'][driver])):
        monkeypatch.delitem(fiona.drvsupport.driver_mode_mingdal['w'], driver)

        with pytest.raises(Exception):
            with fiona.open(path,
                            'w',
                            driver=driver,
                            crs=crs,
                            schema=schema,
                            **create_kwargs) as c:
                c.writerecords(records1)
Esempio n. 2
0
 def _validate(val, val_exp, field_type, driver):
     if (driver == 'MapInfo File' and field_type == 'time'
             and calc_gdal_version_num(2, 0, 0) <= get_gdal_version_num() <
             calc_gdal_version_num(3, 1, 1)):
         return val == '00:00:00'
     if val is None or val == '':
         return True
     return False
Esempio n. 3
0
def test_append_or_driver_error(tmpdir, testdata_generator, driver):
    """ Test if driver supports append mode.

    Some driver only allow a specific schema. These drivers can be excluded by adding them to blacklist_append_drivers.

    """
    if driver == "DGN":
        pytest.xfail("DGN schema has changed")

    if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
        pytest.skip("BNA driver segfaults with gdal 1.11")

    path = str(tmpdir.join(get_temp_filename(driver)))
    schema, crs, records1, records2, test_equal, create_kwargs = testdata_generator(
        driver, range(0, 5), range(5, 10))

    # If driver is not able to write, we cannot test append
    if (driver in driver_mode_mingdal['w'] and get_gdal_version_num() <
            calc_gdal_version_num(*driver_mode_mingdal['w'][driver])):
        return

    # Create test file to append to
    with fiona.open(path,
                    'w',
                    driver=driver,
                    crs=crs,
                    schema=schema,
                    **create_kwargs) as c:

        c.writerecords(records1)

    if (driver in driver_mode_mingdal['a'] and get_gdal_version_num() <
            calc_gdal_version_num(*driver_mode_mingdal['a'][driver])):

        # Test if DriverError is raised for gdal < driver_mode_mingdal
        with pytest.raises(DriverError):
            with fiona.open(path, 'a', driver=driver) as c:
                c.writerecords(records2)

    else:
        # Test if we can append
        with fiona.open(path, 'a', driver=driver) as c:
            c.writerecords(records2)

        if driver in {'FileGDB', 'OpenFileGDB'}:
            open_driver = driver
        else:
            open_driver = None
        with fiona.open(path, driver=open_driver) as c:
            assert c.driver == driver
            items = list(c)
            assert len(items) == len(records1) + len(records2)
            for val_in, val_out in zip(records1 + records2, items):
                assert test_equal(
                    driver, val_in,
                    val_out), "in: {val_in}, out: {val_out}".format(
                        val_in=val_in, val_out=val_out)
Esempio n. 4
0
def test_append_does_not_work_when_gdal_smaller_mingdal(
        tmpdir, driver, testdata_generator, monkeypatch):
    """ Test if driver supports append mode.

    If this test fails, it should be considered to update driver_mode_mingdal in drvsupport.py.

    """

    if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
        pytest.skip("BNA driver segfaults with gdal 1.11")

    path = str(tmpdir.join(get_temp_filename(driver)))
    schema, crs, records1, records2, test_equal, create_kwargs = testdata_generator(
        driver, range(0, 5), range(5, 10))

    # If driver is not able to write, we cannot test append
    if (driver in driver_mode_mingdal['w'] and get_gdal_version_num() <
            calc_gdal_version_num(*driver_mode_mingdal['w'][driver])):
        return

    # Create test file to append to
    with fiona.open(path,
                    'w',
                    driver=driver,
                    crs=crs,
                    schema=schema,
                    **create_kwargs) as c:

        c.writerecords(records1)

    if (driver in driver_mode_mingdal['a'] and get_gdal_version_num() <
            calc_gdal_version_num(*driver_mode_mingdal['a'][driver])):
        # Test if driver really can't append for gdal < driver_mode_mingdal

        monkeypatch.delitem(fiona.drvsupport.driver_mode_mingdal['a'], driver)

        with pytest.raises(Exception):
            with fiona.open(path, 'a', driver=driver) as c:
                c.writerecords(records2)

            if driver in {'FileGDB', 'OpenFileGDB'}:
                open_driver = driver
            else:
                open_driver = None
            with fiona.open(path, driver=open_driver) as c:
                assert c.driver == driver
                items = list(c)
                assert len(items) == len(records1) + len(records2)
                for val_in, val_out in zip(records1 + records2, items):
                    assert test_equal(driver, val_in, val_out)
Esempio n. 5
0
def _driver_supports_milliseconds(driver):
    """ Returns True if the driver supports milliseconds, False otherwise

        Note: this function is not part of Fiona's public API.
    """
    # GDAL 2.0 introduced support for milliseconds
    if get_gdal_version_num() < calc_gdal_version_num(2, 0, 0):
        return False

    if driver in _drivers_not_supporting_milliseconds:
        if _drivers_not_supporting_milliseconds[driver] is None:
            return False
        elif calc_gdal_version_num(
                *_drivers_not_supporting_milliseconds[driver]
        ) < get_gdal_version_num():
            return False

    return True
Esempio n. 6
0
def test_no_append_driver_cannot_append(tmpdir, driver, testdata_generator,
                                        monkeypatch):
    """
    Test if a driver that supports write and not append cannot also append

    If this test fails, it should be considered to enable append support for the respective driver in drvsupport.py.

    """

    monkeypatch.setitem(fiona.drvsupport.supported_drivers, driver, 'raw')

    if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
        pytest.skip("BNA driver segfaults with gdal 1.11")

    path = str(tmpdir.join(get_temp_filename(driver)))
    schema, crs, records1, records2, test_equal, create_kwargs = testdata_generator(
        driver, range(0, 5), range(5, 10))

    # If driver is not able to write, we cannot test append
    if (driver in driver_mode_mingdal['w'] and get_gdal_version_num() <
            calc_gdal_version_num(*driver_mode_mingdal['w'][driver])):
        return

    # Create test file to append to
    with fiona.open(path,
                    'w',
                    driver=driver,
                    crs=crs,
                    schema=schema,
                    **create_kwargs) as c:

        c.writerecords(records1)

    is_good = True
    try:
        with fiona.open(path, 'a', driver=driver) as c:
            c.writerecords(records2)

        if driver in {'FileGDB', 'OpenFileGDB'}:
            open_driver = driver
        else:
            open_driver = None
        with fiona.open(path, driver=open_driver) as c:
            assert c.driver == driver
            items = list(c)
            is_good = is_good and len(items) == len(records1) + len(records2)
            for val_in, val_out in zip(records1 + records2, items):
                is_good = is_good and test_equal(driver, val_in, val_out)
    except:
        is_good = False

    assert not is_good
Esempio n. 7
0
def _driver_supports_timezones(driver, field_type):
    """ Returns True if the driver supports timezones for field_type, False otherwise

        Note: this function is not part of Fiona's public API.
    """
    if field_type in _drivers_not_supporting_timezones and driver in _drivers_not_supporting_timezones[
            field_type]:
        if _drivers_not_supporting_timezones[field_type][driver] is None:
            return False
        elif get_gdal_version_num() < calc_gdal_version_num(
                *_drivers_not_supporting_timezones[field_type][driver]):
            return False
    return True
Esempio n. 8
0
def _driver_converts_field_type_silently_to_str(driver, field_type):
    """ Returns True if the driver converts the field_type silently to str, False otherwise

        Note: this function is not part of Fiona's public API.
    """
    if field_type in _driver_converts_to_str and driver in _driver_converts_to_str[
            field_type]:
        if _driver_converts_to_str[field_type][driver] is None:
            return True
        elif get_gdal_version_num() < calc_gdal_version_num(
                *_driver_converts_to_str[field_type][driver]):
            return True
    return False
Esempio n. 9
0
def test_write_or_driver_error(tmpdir, driver, testdata_generator):
    """
        Test if write mode works.

    """

    if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
        pytest.skip("BNA driver segfaults with gdal 1.11")

    schema, crs, records1, _, test_equal, create_kwargs = testdata_generator(
        driver, range(0, 10), [])
    path = str(tmpdir.join(get_temp_filename(driver)))

    if (driver in driver_mode_mingdal['w'] and get_gdal_version_num() <
            calc_gdal_version_num(*driver_mode_mingdal['w'][driver])):

        # Test if DriverError is raised for gdal < driver_mode_mingdal
        with pytest.raises(DriverError):
            with fiona.open(path,
                            'w',
                            driver=driver,
                            crs=crs,
                            schema=schema,
                            **create_kwargs) as c:
                c.writerecords(records1)

    else:
        # Test if we can write
        with fiona.open(path,
                        'w',
                        driver=driver,
                        crs=crs,
                        schema=schema,
                        **create_kwargs) as c:

            c.writerecords(records1)

        if driver in {'FileGDB', 'OpenFileGDB'}:
            open_driver = driver
        else:
            open_driver = None
        with fiona.open(path, driver=open_driver) as c:
            assert c.driver == driver
            items = list(c)
            assert len(items) == len(records1)
            for val_in, val_out in zip(records1, items):
                assert test_equal(
                    driver, val_in,
                    val_out), "in: {val_in}, out: {val_out}".format(
                        val_in=val_in, val_out=val_out)
Esempio n. 10
0
def _driver_supports_field(driver, field_type):
    """ Returns True if the driver supports the field_type, False otherwise

        Note: this function is not part of Fiona's public API.
    """
    if field_type in _driver_field_type_unsupported and driver in _driver_field_type_unsupported[
            field_type]:
        if _driver_field_type_unsupported[field_type][driver] is None:
            return False
        elif get_gdal_version_num() < calc_gdal_version_num(
                *_driver_field_type_unsupported[field_type][driver]):
            return False

    return True
Esempio n. 11
0
def _driver_supports_mode(driver, mode):
    """ Returns True if driver supports mode, False otherwise

        Note: this function is not part of Fiona's public API.
    """
    if driver not in supported_drivers:
        return False
    if mode not in supported_drivers[driver]:
        return False
    if driver in driver_mode_mingdal[mode]:
        if get_gdal_version_num() < calc_gdal_version_num(
                *driver_mode_mingdal[mode][driver]):
            return False
    return True
Esempio n. 12
0
    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, Path)):
            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)

        if vsi:
            self.path = vfs.vsi_path(path, vsi, archive)
            path = parse_path(self.path)
        else:
            path = parse_path(path)
            self.path = vsi_path(path)

        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.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

            self._check_schema_driver_support()

            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")

        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)

        self.field_skip_log_filter = FieldSkipLogFilter()