[Git][debian-gis-team/fiona][upstream] New upstream version 1.8.18

Bas Couwenberg gitlab at salsa.debian.org
Wed Nov 18 03:57:18 GMT 2020



Bas Couwenberg pushed to branch upstream at Debian GIS Project / fiona


Commits:
1c7d94a6 by Bas Couwenberg at 2020-11-18T04:21:24+01:00
New upstream version 1.8.18
- - - - -


27 changed files:

- + .github/workflows/rstcheck.yml
- .travis.yml
- CHANGES.txt
- fiona/__init__.py
- fiona/_env.pyx
- fiona/_transform.pyx
- fiona/collection.py
- fiona/drvsupport.py
- fiona/errors.py
- fiona/fio/info.py
- fiona/fio/load.py
- fiona/ogrext.pyx
- + pytest.ini
- requirements-ci.txt
- requirements.txt
- − setup.cfg
- setup.py
- tests/conftest.py
- tests/test_bounds.py
- tests/test_collection.py
- + tests/test_cursor_interruptions.py
- tests/test_datetime.py
- + tests/test_driver_options.py
- tests/test_drvsupport.py
- tests/test_fio_load.py
- tests/test_slice.py
- tests/test_transform.py


Changes:

=====================================
.github/workflows/rstcheck.yml
=====================================
@@ -0,0 +1,26 @@
+name: rstcheck
+
+# Run this workflow every time a new commit pushed to your repository
+on: [push, pull_request]
+
+jobs:
+  rstcheck:
+    name: rstcheck
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout code
+        uses: actions/checkout at v2
+
+      - name: Set up Python
+        uses: actions/setup-python at v2
+        with:
+          python-version: 3.8
+
+      - name: Install Python dependencies
+        run: |
+          python -m pip install sphinx==3.2.1 rstcheck==3.3.1
+
+      - name: Run rstcheck
+        run: |
+          rstcheck -r --ignore-directives automodule --ignore-substitutions version,release,today .


=====================================
.travis.yml
=====================================
@@ -56,19 +56,19 @@ matrix:
     # Test all supported python versions with latest stable gdal release
     - python: "2.7"
       env:
-        GDALVERSION="3.1.2"
+        GDALVERSION="3.1.3"
         PROJVERSION="6.3.2"
     - python: "3.6"
       env:
-        GDALVERSION="3.1.2"
+        GDALVERSION="3.1.3"
         PROJVERSION="6.3.2"
     - python: "3.7"
       env:
-        GDALVERSION="3.1.2"
+        GDALVERSION="3.1.3"
         PROJVERSION="6.3.2"
     - python: "3.8"
       env:
-        GDALVERSION="3.1.2"
+        GDALVERSION="3.1.3"
         PROJVERSION="6.3.2"
 
     # Test master
@@ -92,10 +92,8 @@ addons:
     - sqlite3
 
 before_install:
-  - pip install -U pip
-  - pip install setuptools==36.0.1
-  - pip install wheel
-  - "python -m pip install -r requirements-ci.txt"
+  - python -m pip install -U pip
+  - python -m pip install -r requirements-ci.txt
   - python -m pip wheel -r requirements-dev.txt
   - python -m pip install -r requirements-dev.txt
   - export PATH=$GDALINST/gdal-$GDALVERSION/bin:$GDALINST/proj-$PROJVERSION/bin:$PATH
@@ -119,9 +117,6 @@ install:
 script:
   - python -m pytest -m "not wheel" --cov fiona --cov-report term-missing
 
-  # Check documentation
-  - rstcheck -r --ignore-directives automodule --ignore-substitutions version,release,today .
-
 after_script:
   - python setup.py clean
 


=====================================
CHANGES.txt
=====================================
@@ -3,6 +3,17 @@ Changes
 
 All issue numbers are relative to https://github.com/Toblerity/Fiona/issues.
 
+1.8.18 (2020-11-17)
+-------------------
+
+- The precision option of transform has been fixed for the case of
+  GeometryCollections (#971, #972).
+- Added missing --co (creation) option to fio-load (#390).
+- If the certifi package can be imported, its certificate store location will
+  be passed to GDAL during import of fiona._env unless CURL_CA_BUNDLE is
+  already set.
+- Warn when feature fields named "" are found (#955).
+
 1.8.17 (2020-09-09)
 -------------------
 


=====================================
fiona/__init__.py
=====================================
@@ -105,7 +105,7 @@ with fiona._loading.add_gdal_dll_directories():
 
 
 __all__ = ['bounds', 'listlayers', 'open', 'prop_type', 'prop_width']
-__version__ = "1.8.17"
+__version__ = "1.8.18"
 __gdal_version__ = get_gdal_release_name()
 
 gdal_version = get_gdal_version_tuple()


=====================================
fiona/_env.pyx
=====================================
@@ -55,6 +55,11 @@ code_map = {
 
 log = logging.getLogger(__name__)
 
+try:
+    import certifi
+    os.environ.setdefault("CURL_CA_BUNDLE", certifi.where())
+except ImportError:
+    pass
 
 cdef bint is_64bit = sys.maxsize > 2 ** 32
 


=====================================
fiona/_transform.pyx
=====================================
@@ -162,8 +162,8 @@ def _transform_geom(
         g = geom
 
     if precision >= 0:
-
-        if g['type'] == 'Point':
+    
+        def round_point(g):
             coords = list(g['coordinates'])
             x, y = coords[:2]
             x = round(x, precision)
@@ -172,8 +172,10 @@ def _transform_geom(
             if len(coords) == 3:
                 z = coords[2]
                 new_coords.append(round(z, precision))
-
-        elif g['type'] in ['LineString', 'MultiPoint']:
+            return new_coords
+        
+        
+        def round_linestring(g):
             coords = list(zip(*g['coordinates']))
             xp, yp = coords[:2]
             xp = [round(v, precision) for v in xp]
@@ -184,8 +186,10 @@ def _transform_geom(
                 new_coords = list(zip(xp, yp, zp))
             else:
                 new_coords = list(zip(xp, yp))
+            return new_coords
+
 
-        elif g['type'] in ['Polygon', 'MultiLineString']:
+        def round_polygon(g):
             new_coords = []
             for piece in g['coordinates']:
                 coords = list(zip(*piece))
@@ -198,8 +202,9 @@ def _transform_geom(
                     new_coords.append(list(zip(xp, yp, zp)))
                 else:
                     new_coords.append(list(zip(xp, yp)))
+            return new_coords
 
-        elif g['type'] == 'MultiPolygon':
+        def round_multipolygon(g):
             parts = g['coordinates']
             new_coords = []
             for part in parts:
@@ -216,7 +221,24 @@ def _transform_geom(
                     else:
                         inner_coords.append(list(zip(xp, yp)))
                 new_coords.append(inner_coords)
-
-        g['coordinates'] = new_coords
+            return new_coords
+
+        def round_geometry(g):        
+            if g['type'] == 'Point':
+                g['coordinates'] = round_point(g)
+            elif g['type'] in ['LineString', 'MultiPoint']:
+                g['coordinates'] = round_linestring(g)
+            elif g['type'] in ['Polygon', 'MultiLineString']:
+                g['coordinates'] = round_polygon(g)
+            elif g['type'] == 'MultiPolygon':
+                g['coordinates'] = round_multipolygon(g)
+            else:
+                raise RuntimeError("Unsupported geometry type: {}".format(g['type']))
+        
+        if g['type'] == 'GeometryCollection':
+            for _g in g['geometries']:
+                round_geometry(_g)
+        else:
+            round_geometry(g)
 
     return g


=====================================
fiona/collection.py
=====================================
@@ -78,19 +78,6 @@ class Collection(object):
         if archive and not isinstance(archive, string_types):
             raise TypeError("invalid archive: %r" % archive)
 
-
-        # Check GDAL version against drivers
-
-        if driver in driver_mode_mingdal[mode] and get_gdal_version_tuple() < driver_mode_mingdal[mode][driver]:
-            min_gdal_version = ".".join(list(map(str, driver_mode_mingdal[mode][driver])))
-
-            raise DriverError(
-                "{driver} driver requires at least GDAL {min_gdal_version} for mode '{mode}', "
-                "Fiona was compiled against: {gdal}".format(driver=driver,
-                                                            mode=mode,
-                                                            min_gdal_version=min_gdal_version,
-                                                            gdal=get_gdal_release_name()))
-
         self.session = None
         self.iterator = None
         self._len = 0
@@ -104,6 +91,17 @@ class Collection(object):
         self.ignore_fields = ignore_fields
         self.ignore_geometry = bool(ignore_geometry)
 
+        # Check GDAL version against drivers
+        if driver in driver_mode_mingdal[mode] and get_gdal_version_tuple() < driver_mode_mingdal[mode][driver]:
+            min_gdal_version = ".".join(list(map(str, driver_mode_mingdal[mode][driver])))
+
+            raise DriverError(
+                "{driver} driver requires at least GDAL {min_gdal_version} for mode '{mode}', "
+                "Fiona was compiled against: {gdal}".format(driver=driver,
+                                                            mode=mode,
+                                                            min_gdal_version=min_gdal_version,
+                                                            gdal=get_gdal_release_name()))
+
         if vsi:
             self.path = vfs.vsi_path(path, vsi, archive)
             path = parse_path(self.path)
@@ -362,7 +360,7 @@ class Collection(object):
             raise IOError("collection not open for writing")
         self.session.writerecs(records, self)
         self._len = self.session.get_length()
-        self._bounds = self.session.get_extent()
+        self._bounds = None
 
     def write(self, record):
         """Stages a record for writing to disk."""
@@ -448,7 +446,7 @@ class Collection(object):
             self.session.sync(self)
             new_len = self.session.get_length()
             self._len = new_len > self._len and new_len or self._len
-            self._bounds = self.session.get_extent()
+            self._bounds = None
 
     def close(self):
         """In append or write mode, flushes data to disk, then ends


=====================================
fiona/drvsupport.py
=====================================
@@ -41,7 +41,6 @@ supported_drivers = dict([
     # multi-layer
     ("FileGDB", "raw"),
     ("OpenFileGDB", "r"),
-    ("FlatGeobuf", "r"),
     # ESRI Personal GeoDatabase 	PGeo 	No 	Yes 	No, needs ODBC library
     # ESRI ArcSDE 	SDE 	No 	Yes 	No, needs ESRI SDE
     # ESRIJSON 	ESRIJSON 	No 	Yes 	Yes 
@@ -49,6 +48,7 @@ supported_drivers = dict([
     # ESRI Shapefile 	ESRI Shapefile 	Yes 	Yes 	Yes
     ("ESRI Shapefile", "raw"),
     # FMEObjects Gateway 	FMEObjects Gateway 	No 	Yes 	No, needs FME
+    ("FlatGeobuf", "rw"),
     # GeoJSON 	GeoJSON 	Yes 	Yes 	Yes
     ("GeoJSON", "raw"),
     # GeoJSONSeq 	GeoJSON sequences 	Yes 	Yes 	Yes 
@@ -150,11 +150,13 @@ supported_drivers = dict([
 driver_mode_mingdal = {
 
     'r': {'GPKG': (1, 11, 0),
-          'GeoJSONSeq': (2, 4, 0)},
+          'GeoJSONSeq': (2, 4, 0),
+          'FlatGeobuf': (3, 1, 0)},
 
     'w': {'GPKG': (1, 11, 0),
           'PCIDSK': (2, 0, 0),
-          'GeoJSONSeq': (2, 4, 0)},
+          'GeoJSONSeq': (2, 4, 0),
+          'FlatGeobuf': (3, 1, 3)},
 
     'a': {'GPKG': (1, 11, 0),
           'GeoJSON': (2, 1, 0),
@@ -249,7 +251,8 @@ _driver_field_type_unsupported = {
         'BNA': None,
         'DXF': None,
         'PCIDSK': (2, 1, 0),
-        'FileGDB': None
+        'FileGDB': None,
+        'FlatGeobuf': None
     },
     'datetime': {
         'ESRI Shapefile': None,
@@ -266,7 +269,8 @@ _driver_field_type_unsupported = {
         'BNA': None,
         'DXF': None,
         'PCIDSK': (2, 1, 0),
-        'FileGDB': None
+        'FileGDB': None,
+        'FlatGeobuf': None
     }
 }
 


=====================================
fiona/errors.py
=====================================
@@ -65,3 +65,7 @@ class GDALVersionError(FionaError):
 
 class FionaDeprecationWarning(UserWarning):
     """A warning about deprecation of Fiona features"""
+
+
+class FeatureWarning(UserWarning):
+    """A warning about serialization of a feature"""


=====================================
fiona/fio/info.py
=====================================
@@ -9,6 +9,7 @@ from cligj import indent_opt
 
 import fiona
 import fiona.crs
+from fiona.errors import DriverError
 from fiona.fio import options, with_context_env
 
 
@@ -47,7 +48,13 @@ def info(ctx, input, indent, meta_member, layer):
     try:
         with fiona.open(input, layer=layer) as src:
             info = src.meta
-            info.update(bounds=src.bounds, name=src.name)
+            info.update(name=src.name)
+            try:
+                info.update(bounds=src.bounds)
+            except DriverError:
+                info.update(bounds=None)
+                logger.debug("Setting 'bounds' to None - driver "
+                             "was not able to calculate bounds")
             try:
                 info.update(count=len(src))
             except TypeError:


=====================================
fiona/fio/load.py
=====================================
@@ -13,6 +13,37 @@ from fiona.schema import FIELD_TYPES_MAP_REV
 from fiona.transform import transform_geom
 
 
+def _cb_key_val(ctx, param, value):
+    """
+    click callback to validate `--opt KEY1=VAL1 --opt KEY2=VAL2` and collect
+    in a dictionary like the one below, which is what the CLI function receives.
+    If no value or `None` is received then an empty dictionary is returned.
+
+        {
+            'KEY1': 'VAL1',
+            'KEY2': 'VAL2'
+        }
+
+    Note: `==VAL` breaks this as `str.split('=', 1)` is used.
+
+    """
+    if not value:
+        return {}
+    else:
+        out = {}
+        for pair in value:
+            if "=" not in pair:
+                raise click.BadParameter(
+                    "Invalid syntax for KEY=VAL arg: {}".format(pair)
+                )
+            else:
+                k, v = pair.split("=", 1)
+                k = k.lower()
+                v = v.lower()
+                out[k] = None if v.lower() in ["none", "null", "nil", "nada"] else v
+        return out
+
+
 @click.command(short_help="Load GeoJSON to a dataset in another format.")
 @click.argument('output', required=True)
 @click.option('-f', '--format', '--driver', 'driver', required=True,
@@ -21,16 +52,30 @@ from fiona.transform import transform_geom
 @click.option('--dst-crs', '--dst_crs',
               help="Destination CRS.  Defaults to --src-crs when not given.")
 @cligj.features_in_arg
- at click.option('--layer', metavar="INDEX|NAME", callback=options.cb_layer,
-              help="Load features into specified layer.  Layers use "
-                   "zero-based numbering when accessed by index.")
+ at click.option(
+    "--layer",
+    metavar="INDEX|NAME",
+    callback=options.cb_layer,
+    help="Load features into specified layer.  Layers use "
+    "zero-based numbering when accessed by index.",
+)
+ at click.option(
+    "--co",
+    "--profile",
+    "creation_options",
+    metavar="NAME=VALUE",
+    multiple=True,
+    callback=_cb_key_val,
+    help="Driver specific creation options. See the documentation for the selected output driver for more information.",
+)
 @click.pass_context
 @with_context_env
-def load(ctx, output, driver, src_crs, dst_crs, features, layer):
+def load(ctx, output, driver, src_crs, dst_crs, features, layer, creation_options):
     """Load features from JSON to a file in another format.
 
     The input is a GeoJSON feature collection or optionally a sequence of
     GeoJSON feature objects.
+
     """
     logger = logging.getLogger(__name__)
 
@@ -60,11 +105,14 @@ def load(ctx, output, driver, src_crs, dst_crs, features, layer):
             for k, v in first['properties'].items()])
 
         with fiona.open(
-                output, 'w',
-                driver=driver,
-                crs=dst_crs,
-                schema=schema,
-                layer=layer) as dst:
+            output,
+            "w",
+            driver=driver,
+            crs=dst_crs,
+            schema=schema,
+            layer=layer,
+            **creation_options
+        ) as dst:
             dst.write(first)
             dst.writerecords(source)
 


=====================================
fiona/ogrext.pyx
=====================================
@@ -30,7 +30,7 @@ from fiona.env import Env
 from fiona.errors import (
     DriverError, DriverIOError, SchemaError, CRSError, FionaValueError,
     TransactionError, GeometryTypeValidationError, DatasetDeleteError,
-    FionaDeprecationWarning)
+    FeatureWarning, FionaDeprecationWarning)
 from fiona.compat import OrderedDict
 from fiona.rfc3339 import parse_date, parse_datetime, parse_time
 from fiona.rfc3339 import FionaDateType, FionaDateTimeType, FionaTimeType
@@ -192,12 +192,14 @@ cdef class FeatureBuilder:
         for i in range(OGR_F_GetFieldCount(feature)):
             fdefn = OGR_F_GetFieldDefnRef(feature, i)
             if fdefn == NULL:
-                raise ValueError("Null feature definition")
+                raise ValueError("NULL field definition at index {}".format(i))
             key_c = OGR_Fld_GetNameRef(fdefn)
             if key_c == NULL:
-                raise ValueError("Null field name reference")
+                raise ValueError("NULL field name reference at index {}".format(i))
             key_b = key_c
             key = key_b.decode(encoding)
+            if not key:
+                warnings.warn("Empty field name at index {}".format(i))
 
             if key in ignore_fields:
                 continue
@@ -498,12 +500,14 @@ cdef class Session:
     cdef object _fileencoding
     cdef object _encoding
     cdef object collection
+    cdef bint cursor_interrupted
 
     def __init__(self):
         self.cogr_ds = NULL
         self.cogr_layer = NULL
         self._fileencoding = None
         self._encoding = None
+        self.cursor_interrupted = False
 
     def __dealloc__(self):
         self.stop()
@@ -625,7 +629,7 @@ cdef class Session:
     def get_length(self):
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        return OGR_L_GetFeatureCount(self.cogr_layer, 0)
+        return self._get_feature_count(0)
 
     def get_driver(self):
         cdef void *cogr_driver = GDALGetDatasetDriver(self.cogr_ds)
@@ -662,15 +666,15 @@ cdef class Session:
         for i from 0 <= i < n:
             cogr_fielddefn = OGR_FD_GetFieldDefn(cogr_featuredefn, i)
             if cogr_fielddefn == NULL:
-                raise ValueError("Null field definition")
+                raise ValueError("NULL field definition at index {}".format(i))
 
             key_c = OGR_Fld_GetNameRef(cogr_fielddefn)
+            if key_c == NULL:
+                raise ValueError("NULL field name reference at index {}".format(i))
             key_b = key_c
-
-            if not bool(key_b):
-                raise ValueError("Invalid field name ref: %s" % key)
-
             key = key_b.decode(encoding)
+            if not key:
+                warnings.warn("Empty field name at index {}".format(i), FeatureWarning)
 
             if key in ignore_fields:
                 log.debug("By request, ignoring field %r", key)
@@ -848,7 +852,18 @@ cdef class Session:
             raise ValueError("Null layer")
 
         result = OGR_L_GetExtent(self.cogr_layer, &extent, 1)
+        self.cursor_interrupted = True
+        if result != OGRERR_NONE:
+            raise DriverError("Driver was not able to calculate bounds")
         return (extent.MinX, extent.MinY, extent.MaxX, extent.MaxY)
+        
+    
+    cdef int _get_feature_count(self, force=0):
+        if self.cogr_layer == NULL:
+            raise ValueError("Null layer")
+        self.cursor_interrupted = True
+        return OGR_L_GetFeatureCount(self.cogr_layer, force)
+    
 
     def has_feature(self, fid):
         """Provides access to feature data by FID.
@@ -900,7 +915,7 @@ cdef class Session:
             index = item
             # from the back
             if index < 0:
-                ftcount = OGR_L_GetFeatureCount(self.cogr_layer, 0)
+                ftcount = self._get_feature_count(0)
                 if ftcount == -1:
                     raise IndexError(
                         "collection's dataset does not support negative indexes")
@@ -992,7 +1007,8 @@ cdef class WritingSession(Session):
 
             if not CPLCheckForFile(path_c, NULL):
                 log.debug("File doesn't exist. Creating a new one...")
-                cogr_ds = gdal_create(cogr_driver, path_c, {})
+                with Env(GDAL_VALIDATE_CREATION_OPTIONS="NO"):
+                    cogr_ds = gdal_create(cogr_driver, path_c, kwargs)
 
             else:
                 if collection.driver == "GeoJSON":
@@ -1374,9 +1390,9 @@ cdef class Iterator:
                 warnings.warn("Layer does not support" \
                         " OLC_FASTFEATURECOUNT, negative slices or start values other than zero" \
                         " may be slow.", RuntimeWarning)
-            self.ftcount = OGR_L_GetFeatureCount(session.cogr_layer, 1)
+            self.ftcount = session._get_feature_count(1)
         else:
-            self.ftcount = OGR_L_GetFeatureCount(session.cogr_layer, 0)
+            self.ftcount = session._get_feature_count(0)
 
         if self.ftcount == -1 and ((start is not None and start < 0) or
                               (stop is not None and stop < 0)):
@@ -1450,20 +1466,27 @@ cdef class Iterator:
                 raise StopIteration
 
         # Set read cursor to next_item position
-        if self.step > 1 and self.fastindex:
-            exc_wrap_int(OGR_L_SetNextByIndex(session.cogr_layer, self.next_index))
-        elif self.step > 1 and not self.fastindex and not self.next_index == self.start:
-            # GDALs default implementation of SetNextByIndex is calling ResetReading() and then
-            # calling GetNextFeature n times. We can shortcut that if we know the previous index.
-            # OGR_L_GetNextFeature increments cursor by 1, therefore self.step - 1 as one increment was performed when feature is read
-            for _ in range(self.step - 1):
-                cogr_feature = OGR_L_GetNextFeature(session.cogr_layer)
-                if cogr_feature == NULL:
-                    raise StopIteration
-        elif self.step > 1 and not self.fastindex and self.next_index == self.start:
-            exc_wrap_int(OGR_L_SetNextByIndex(session.cogr_layer, self.next_index))
-        elif self.step < 0:
+        if session.cursor_interrupted:
+            if not self.fastindex:
+                warnings.warn("Sequential read of iterator was interrupted. Resetting iterator. "
+                              "This can negatively impact the performance.", RuntimeWarning)
             exc_wrap_int(OGR_L_SetNextByIndex(session.cogr_layer, self.next_index))
+            session.cursor_interrupted = False
+        else:
+            if self.step > 1 and self.fastindex:
+                exc_wrap_int(OGR_L_SetNextByIndex(session.cogr_layer, self.next_index))
+            elif self.step > 1 and not self.fastindex and not self.next_index == self.start:
+                # GDALs default implementation of SetNextByIndex is calling ResetReading() and then
+                # calling GetNextFeature n times. We can shortcut that if we know the previous index.
+                # OGR_L_GetNextFeature increments cursor by 1, therefore self.step - 1 as one increment was performed when feature is read
+                for _ in range(self.step - 1):
+                    cogr_feature = OGR_L_GetNextFeature(session.cogr_layer)
+                    if cogr_feature == NULL:
+                        raise StopIteration
+            elif self.step > 1 and not self.fastindex and self.next_index == self.start:
+                exc_wrap_int(OGR_L_SetNextByIndex(session.cogr_layer, self.next_index))
+            elif self.step < 0:
+                exc_wrap_int(OGR_L_SetNextByIndex(session.cogr_layer, self.next_index))
 
         # set the next index
         self.next_index += self.step


=====================================
pytest.ini
=====================================
@@ -0,0 +1,13 @@
+[pytest]
+filterwarnings =
+    ignore:.*Sequential read of iterator was interrupted*:RuntimeWarning
+    ignore:.*negative slices or start values other than zero may be slow*:RuntimeWarning
+    ignore:.*negative step size may be slow*:RuntimeWarning
+    ignore:.*is buggy and will be removed in Fiona 2.0.*
+
+markers = 
+    iconv: marks tests that require gdal to be compiled with iconv
+    network: marks tests that require a network connection
+    wheel: marks test that only works when installed from wheel
+
+testpaths = tests


=====================================
requirements-ci.txt
=====================================
@@ -1,6 +1 @@
 coveralls
-# sphinx 3.x does not support python 2.7
-sphinx==3.0.2 ; python_version > '3.0'
-sphinx==1.8.5 ; python_version < '3.0'
-rstcheck==3.3.1
-


=====================================
requirements.txt
=====================================
@@ -4,3 +4,4 @@ cligj==0.5.0
 munch==2.3.2
 six==1.11.0
 enum34==1.1.6 ; python_version < '3.4'
+certifi


=====================================
setup.cfg deleted
=====================================
@@ -1,7 +0,0 @@
-[tool:pytest]
-testpaths = tests
-markers =
-    slow
-    network
-    iconv
-    wheel


=====================================
setup.py
=====================================
@@ -284,6 +284,7 @@ elif "clean" not in sys.argv:
 
 requirements = [
     'attrs>=17',
+    'certifi',
     'click>=4.0,<8',
     'cligj>=0.5',
     'click-plugins>=1.0',


=====================================
tests/conftest.py
=====================================
@@ -28,7 +28,8 @@ driver_extensions = {'DXF': 'dxf',
                      'GeoJSONSeq': 'geojsons',
                      'GMT': 'gmt',
                      'OGR_GMT': 'gmt',
-                     'BNA': 'bna'}
+                     'BNA': 'bna',
+                     'FlatGeobuf': 'fgb'}
 
 
 def pytest_report_header(config):
@@ -395,6 +396,12 @@ def testdata_generator():
         }
         return special_records2.get(driver, get_records(driver, range))
 
+    def get_create_kwargs(driver):
+        kwargs = {
+            'FlatGeobuf': {'SPATIAL_INDEX': False}
+        }
+        return kwargs.get(driver, {})
+
     def test_equal(driver, val_in, val_out):
         is_good = True
         is_good = is_good and val_in['geometry'] == val_out['geometry']
@@ -437,7 +444,7 @@ def testdata_generator():
             the properties of the generated records can be found in a record
         """
         return get_schema(driver), get_crs(driver), get_records(driver, range1), get_records2(driver, range2),\
-               test_equal
+               test_equal, get_create_kwargs(driver)
 
     return _testdata_generator
 


=====================================
tests/test_bounds.py
=====================================
@@ -1,4 +1,9 @@
+import pytest
 import fiona
+from fiona.drvsupport import supported_drivers, _driver_supports_mode
+from fiona.errors import DriverError
+from .conftest import driver_extensions
+from fiona.env import GDALVersion
 
 
 def test_bounds_point():
@@ -17,5 +22,48 @@ def test_bounds_polygon():
 
 
 def test_bounds_z():
-    g = {'type': 'Point', 'coordinates': [10,10,10]}
+    g = {'type': 'Point', 'coordinates': [10, 10, 10]}
     assert fiona.bounds(g) == (10, 10, 10, 10)
+
+
+ignore_write_drivers = set(['CSV', 'GPX', 'GPSTrackMaker', 'DXF', 'DGN', 'MapInfo File'])
+write_drivers = [driver for driver, raw in supported_drivers.items() if
+                 _driver_supports_mode(driver, 'w') and driver not in ignore_write_drivers]
+
+
+ at pytest.mark.parametrize('driver', write_drivers)
+def test_bounds(tmpdir, driver):
+    """Test if bounds are correctly calculated after writing
+
+    """
+
+    if driver == 'BNA' and GDALVersion.runtime() < GDALVersion(2, 0):
+        # BNA driver segfaults with gdal 1.11
+        return
+
+    extension = driver_extensions.get(driver, "bar")
+    path = str(tmpdir.join('foo.{}'.format(extension)))
+
+    with fiona.open(path, 'w',
+                    driver=driver,
+                    schema={'geometry': 'Point',
+                            'properties': [('title', 'str')]},
+                    fiona_force_driver=True) as c:
+
+        c.writerecords([{'geometry': {'type': 'Point', 'coordinates': (1.0, 10.0)},
+                         'properties': {'title': 'One'}}])
+
+        try:
+            bounds = c.bounds
+            assert bounds == (1.0, 10.0, 1.0, 10.0)
+        except Exception as e:
+            assert isinstance(e, DriverError)
+
+        c.writerecords([{'geometry': {'type': 'Point', 'coordinates': (2.0, 20.0)},
+                         'properties': {'title': 'Two'}}])
+
+        try:
+            bounds = c.bounds
+            assert bounds == (1.0, 10.0, 2.0, 20.0)
+        except Exception as e:
+            assert isinstance(e, DriverError)


=====================================
tests/test_collection.py
=====================================
@@ -939,3 +939,26 @@ def test_mask_polygon_triangle(tmpdir, driver, filename):
         items = list(
             c.items(mask={'type': 'Polygon', 'coordinates': (((2.0, 2.0), (4.0, 4.0), (4.0, 6.0), (2.0, 2.0)),)}))
         assert len(items) == 15
+
+
+def test_collection__empty_column_name(tmpdir):
+    """Based on pull #955"""
+    tmpfile = str(tmpdir.join("test_empty.geojson"))
+    with pytest.warns(UserWarning, match="Empty field name at index 0"):
+        with fiona.open(tmpfile,  "w", driver="GeoJSON", schema={
+                "geometry": "Point",
+                "properties": {"": "str", "name": "str"}
+        }) as tmp:
+            tmp.writerecords([{
+                "geometry": {"type": "Point", "coordinates": [ 8, 49 ] },
+                "properties": { "": "", "name": "test" }
+            }])
+
+    with fiona.open(tmpfile) as tmp:
+        with pytest.warns(UserWarning, match="Empty field name at index 0"):
+            assert tmp.schema == {
+                "geometry": "Point",
+                "properties": {"": "str", "name": "str"}
+            }
+        with pytest.warns(UserWarning, match="Empty field name at index 0"):
+            next(tmp)


=====================================
tests/test_cursor_interruptions.py
=====================================
@@ -0,0 +1,158 @@
+import fiona
+import pytest
+from fiona.drvsupport import driver_mode_mingdal, _driver_supports_mode
+from fiona.errors import DriverError
+from tests.conftest import get_temp_filename
+
+
+ at pytest.mark.parametrize('driver', [driver for driver in driver_mode_mingdal['w'].keys()
+                                    if _driver_supports_mode(driver, 'w')])
+def test_write_getextent(tmpdir, driver, testdata_generator):
+    """
+        Test if a call to OGR_L_GetExtent has side effects for writing
+
+    """
+
+    schema, crs, records1, records2, test_equal, create_kwargs = testdata_generator(driver, range(0, 10), range(10, 20))
+    path = str(tmpdir.join(get_temp_filename(driver)))
+    positions = set([int(r['properties']['position']) for r in records1 + records2])
+
+    with fiona.open(path, 'w',
+                    driver=driver,
+                    crs=crs,
+                    schema=schema,
+                    **create_kwargs) as c:
+        c.writerecords(records1)
+
+        # Call to OGR_L_GetExtent
+        try:
+            c.bounds
+        except DriverError:
+            pass
+
+        c.writerecords(records2)
+
+    with fiona.open(path) as c:
+        data = set([int(f['properties']['position']) for f in c])
+        assert len(positions) == len(data)
+        for p in positions:
+            assert p in data
+
+
+ at pytest.mark.parametrize('driver', [driver for driver in driver_mode_mingdal['w'].keys()
+                                    if _driver_supports_mode(driver, 'w')])
+def test_read_getextent(tmpdir, driver, testdata_generator):
+    """
+        Test if a call to OGR_L_GetExtent has side effects for reading
+
+    """
+
+    schema, crs, records1, records2, test_equal, create_kwargs = testdata_generator(driver, range(0, 10), range(10, 20))
+    path = str(tmpdir.join(get_temp_filename(driver)))
+    positions = set([int(r['properties']['position']) for r in records1 + records2])
+
+    with fiona.open(path, 'w',
+                    driver=driver,
+                    crs=crs,
+                    schema=schema,
+                    **create_kwargs) as c:
+        c.writerecords(records1)
+        c.writerecords(records2)
+
+    with fiona.open(path) as c:
+        data = set()
+        for _ in range(len(records1)):
+            f = next(c)
+            data.add(int(f['properties']['position']))
+
+        # Call to OGR_L_GetExtent
+        try:
+            c.bounds
+        except DriverError:
+            pass
+
+        for _ in range(len(records1)):
+            f = next(c)
+            data.add(int(f['properties']['position']))
+        assert len(positions) == len(data)
+        for p in positions:
+            assert p in data
+
+
+ at pytest.mark.parametrize('driver', [driver for driver in driver_mode_mingdal['w'].keys()
+                                    if _driver_supports_mode(driver, 'w')])
+def test_write_getfeaturecount(tmpdir, driver, testdata_generator):
+    """
+        Test if a call to OGR_L_GetFeatureCount has side effects for writing
+
+    """
+
+    schema, crs, records1, records2, test_equal, create_kwargs = testdata_generator(driver, range(0, 10), range(10, 20))
+    path = str(tmpdir.join(get_temp_filename(driver)))
+    positions = set([int(r['properties']['position']) for r in records1 + records2])
+
+    with fiona.open(path, 'w',
+                    driver=driver,
+                    crs=crs,
+                    schema=schema,
+                    **create_kwargs) as c:
+        c.writerecords(records1)
+
+        # Call to OGR_L_GetFeatureCount
+        try:
+            assert len(c) == len(records1)
+        except TypeError:
+            pass
+        c.writerecords(records2)
+
+    with fiona.open(path) as c:
+        data = set([int(f['properties']['position']) for f in c])
+        assert len(positions) == len(data)
+        for p in positions:
+            assert p in data
+
+
+ at pytest.mark.parametrize('driver', [driver for driver in driver_mode_mingdal['w'].keys()
+                                    if _driver_supports_mode(driver, 'w')])
+def test_read_getfeaturecount(tmpdir, driver, testdata_generator):
+    """
+        Test if a call to OGR_L_GetFeatureCount has side effects for reading
+
+    """
+
+    schema, crs, records1, records2, test_equal, create_kwargs = testdata_generator(driver, range(0, 10), range(10, 20))
+    path = str(tmpdir.join(get_temp_filename(driver)))
+    positions = set([int(r['properties']['position']) for r in records1 + records2])
+
+    with fiona.open(path, 'w',
+                    driver=driver,
+                    crs=crs,
+                    schema=schema,
+                    **create_kwargs) as c:
+        c.writerecords(records1)
+        c.writerecords(records2)
+
+    with fiona.open(path) as c:
+        data = set()
+        for _ in range(len(records1)):
+            f = next(c)
+            data.add(int(f['properties']['position']))
+
+        # Call to OGR_L_GetFeatureCount
+        try:
+            assert len(data) == len(records1)
+        except TypeError:
+            pass
+
+        for _ in range(len(records1)):
+            f = next(c)
+            data.add(int(f['properties']['position']))
+
+        try:
+            assert len(data) == len(records1 + records2)
+        except TypeError:
+            pass
+
+        assert len(positions) == len(data)
+        for p in positions:
+            assert p in data
\ No newline at end of file


=====================================
tests/test_datetime.py
=====================================
@@ -13,7 +13,7 @@ from fiona.env import GDALVersion
 import datetime
 from fiona.drvsupport import (supported_drivers, driver_mode_mingdal, _driver_converts_field_type_silently_to_str,
                               _driver_supports_field, _driver_converts_to_str, _driver_supports_timezones,
-                              _driver_supports_milliseconds)
+                              _driver_supports_milliseconds, _driver_supports_mode)
 import pytz
 from pytz import timezone
 
@@ -253,9 +253,7 @@ def generate_testcases():
     for field_type in ['time', 'datetime', 'date']:
         # Select only driver that are capable of writing fields
         for driver, raw in supported_drivers.items():
-            if ('w' in raw and
-                    (driver not in driver_mode_mingdal['w'] or
-                     gdal_version >= GDALVersion(*driver_mode_mingdal['w'][driver][:2]))):
+            if _driver_supports_mode(driver, 'w'):
                 if _driver_supports_field(driver, field_type):
                     if _driver_converts_field_type_silently_to_str(driver, field_type):
                         _test_cases_datefield_to_str.append((driver, field_type))
@@ -284,7 +282,7 @@ def test_datefield(tmpdir, driver, field_type):
         elif field_type == 'datetime':
 
             # some drivers do not support timezones. In this case, Fiona converts datetime fields with a timezone other
-            # than UTC to UTC. Thus, both the dateime read by Fiona, as well as expected value are first converted to
+            # than UTC to UTC. Thus, both the datetime read by Fiona, as well as expected value are first converted to
             # UTC before compared.
 
             # Milliseconds
@@ -585,9 +583,8 @@ def test_datetime_field_type_marked_not_supported_is_not_supported(tmpdir, drive
 
     """
 
-    if driver == "BNA" and gdal_version < GDALVersion(2, 0):
-        # BNA driver segfaults with gdal 1.11
-        return
+    if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
+        pytest.skip("BNA driver segfaults with gdal 1.11")
 
     monkeypatch.delitem(fiona.drvsupport._driver_field_type_unsupported[field_type], driver)
 
@@ -621,8 +618,7 @@ def generate_tostr_testcases():
     for field_type in _driver_converts_to_str:
         for driver in _driver_converts_to_str[field_type]:
             driver_supported = driver in supported_drivers
-            driver_can_write = (driver not in driver_mode_mingdal['w'] or
-                                gdal_version >= GDALVersion(*driver_mode_mingdal['w'][driver][:2]))
+            driver_can_write = _driver_supports_mode(driver, 'w')
             field_supported = _driver_supports_field(driver, field_type)
             converts_to_str = _driver_converts_field_type_silently_to_str(driver, field_type)
             if driver_supported and driver_can_write and converts_to_str and field_supported:


=====================================
tests/test_driver_options.py
=====================================
@@ -0,0 +1,30 @@
+import os
+import tempfile
+from collections import OrderedDict
+import glob
+import fiona
+from tests.conftest import get_temp_filename, requires_gdal2
+
+
+ at requires_gdal2
+def test_gml_format_option():
+    """ Test GML dataset creation option FORMAT (see https://github.com/Toblerity/Fiona/issues/968)"""
+
+    schema = {'geometry': 'Point', 'properties': OrderedDict([('position', 'int')])}
+    records = [{'geometry': {'type': 'Point', 'coordinates': (0.0, float(i))}, 'properties': {'position': i}} for i in
+               range(10)]
+
+    tmpdir = tempfile.mkdtemp()
+    fpath = os.path.join(tmpdir, get_temp_filename('GML'))
+
+    with fiona.open(fpath,
+                    'w',
+                    driver="GML",
+                    schema=schema,
+                    FORMAT="GML3") as out:
+        out.writerecords(records)
+
+    xsd_path = glob.glob(os.path.join(tmpdir, "*.xsd"))[0]
+    with open(xsd_path) as f:
+        xsd = f.read()
+        assert "http://schemas.opengis.net/gml/3.1.1" in xsd


=====================================
tests/test_drvsupport.py
=====================================
@@ -5,6 +5,7 @@ from .conftest import requires_gdal24, get_temp_filename
 from fiona.drvsupport import supported_drivers, driver_mode_mingdal
 import fiona.drvsupport
 from fiona.env import GDALVersion
+from fiona._env import calc_gdal_version_num, get_gdal_version_num
 from fiona.errors import DriverError
 
 
@@ -23,30 +24,30 @@ def test_write_or_driver_error(tmpdir, driver, testdata_generator):
     """
 
     if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
-        # BNA driver segfaults with gdal 1.11
-        return
+        pytest.skip("BNA driver segfaults with gdal 1.11")
 
-    schema, crs, records1, _, test_equal = testdata_generator(driver, range(0, 10), [])
+    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 GDALVersion.runtime() < GDALVersion(
-            *driver_mode_mingdal['w'][driver][:2]):
+    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) as c:
+                            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) as c:
+                        schema=schema,
+                        **create_kwargs) as c:
 
             c.writerecords(records1)
 
@@ -73,21 +74,24 @@ def test_write_does_not_work_when_gdal_smaller_mingdal(tmpdir, driver, testdata_
     """
 
     if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
-        # BNA driver segfaults with gdal 1.11
-        return
+        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 = testdata_generator(driver, range(0, 10), [])
+    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 GDALVersion.runtime() < GDALVersion(
-            *driver_mode_mingdal['w'][driver][:2]):
+    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) as c:
+                            schema=schema,
+                            **create_kwargs) as c:
                 c.writerecords(records1)
 
 
@@ -100,27 +104,27 @@ def test_append_or_driver_error(tmpdir, testdata_generator, driver):
     """
 
     if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
-        # BNA driver segfaults with gdal 1.11
-        return
+        pytest.skip("BNA driver segfaults with gdal 1.11")
 
     path = str(tmpdir.join(get_temp_filename(driver)))
-    schema, crs, records1, records2, test_equal = testdata_generator(driver, range(0, 5), range(5, 10))
+    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 GDALVersion.runtime() < GDALVersion(
-            *driver_mode_mingdal['w'][driver][:2]):
+    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) as c:
+                    schema=schema,
+                    **create_kwargs) as c:
 
         c.writerecords(records1)
 
-    if driver in driver_mode_mingdal['a'] and GDALVersion.runtime() < GDALVersion(
-            *driver_mode_mingdal['a'][driver][:2]):
+    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):
@@ -157,27 +161,27 @@ def test_append_does_not_work_when_gdal_smaller_mingdal(tmpdir, driver, testdata
     """
 
     if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
-        # BNA driver segfaults with gdal 1.11
-        return
+        pytest.skip("BNA driver segfaults with gdal 1.11")
 
     path = str(tmpdir.join(get_temp_filename(driver)))
-    schema, crs, records1, records2, test_equal = testdata_generator(driver, range(0, 5), range(5, 10))
+    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 GDALVersion.runtime() < GDALVersion(
-            *driver_mode_mingdal['w'][driver][:2]):
+    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) as c:
+                    schema=schema,
+                    **create_kwargs) as c:
 
         c.writerecords(records1)
 
-    if driver in driver_mode_mingdal['a'] and GDALVersion.runtime() < GDALVersion(
-            *driver_mode_mingdal['a'][driver][:2]):
+    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)
@@ -208,7 +212,7 @@ def test_no_write_driver_cannot_write(tmpdir, driver, testdata_generator, monkey
     """
 
     monkeypatch.setitem(fiona.drvsupport.supported_drivers, driver, 'rw')
-    schema, crs, records1, _, test_equal = testdata_generator(driver, range(0, 5), [])
+    schema, crs, records1, _, test_equal, create_kwargs = testdata_generator(driver, range(0, 5), [])
 
     if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
         pytest.skip("BNA driver segfaults with gdal 1.11")
@@ -222,7 +226,8 @@ def test_no_write_driver_cannot_write(tmpdir, driver, testdata_generator, monkey
         with fiona.open(path, 'w',
                         driver=driver,
                         crs=crs,
-                        schema=schema) as c:
+                        schema=schema,
+                        **create_kwargs) as c:
             c.writerecords(records1)
 
 
@@ -239,22 +244,22 @@ def test_no_append_driver_cannot_append(tmpdir, driver, testdata_generator, monk
     monkeypatch.setitem(fiona.drvsupport.supported_drivers, driver, 'raw')
 
     if driver == "BNA" and GDALVersion.runtime() < GDALVersion(2, 0):
-        # BNA driver segfaults with gdal 1.11
-        return
+        pytest.skip("BNA driver segfaults with gdal 1.11")
 
     path = str(tmpdir.join(get_temp_filename(driver)))
-    schema, crs, records1, records2, test_equal = testdata_generator(driver, range(0, 5), range(5, 10))
+    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 GDALVersion.runtime() < GDALVersion(
-            *driver_mode_mingdal['w'][driver][:2]):
+    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) as c:
+                    schema=schema,
+                    **create_kwargs) as c:
 
         c.writerecords(records1)
 


=====================================
tests/test_fio_load.py
=====================================
@@ -4,7 +4,6 @@
 import json
 import os
 import shutil
-import sys
 
 import pytest
 
@@ -34,7 +33,6 @@ def test_collection(tmpdir, feature_collection, runner):
     assert len(fiona.open(tmpfile)) == 2
 
 
-
 def test_seq_rs(feature_seq_pp_rs, tmpdir, runner):
     tmpfile = str(tmpdir.mkdir('tests').join('test_seq_rs.shp'))
     result = runner.invoke(
@@ -123,3 +121,15 @@ def test_fio_load_layer(tmpdir, runner):
 
     finally:
         shutil.rmtree(outdir)
+
+
+ at pytest.mark.iconv
+def test_creation_options(tmpdir, runner, feature_seq):
+    tmpfile = str(tmpdir.mkdir("tests").join("test.shp"))
+    result = runner.invoke(
+        main_group,
+        ["load", "-f", "Shapefile", "--co", "ENCODING=LATIN1", tmpfile],
+        feature_seq,
+    )
+    assert result.exit_code == 0
+    assert tmpdir.join("tests/test.cpg").read() == "LATIN1"


=====================================
tests/test_slice.py
=====================================
@@ -70,12 +70,17 @@ def slice_dataset_path(request):
     schema = get_schema(driver)
     records = get_records(driver, range(min_id, max_id + 1))
 
+    create_kwargs = {}
+    if driver == 'FlatGeobuf':
+        create_kwargs['SPATIAL_INDEX'] = False
+
     tmpdir = tempfile.mkdtemp()
     path = os.path.join(tmpdir, get_temp_filename(driver))
 
     with fiona.open(path, 'w',
                     driver=driver,
-                    schema=schema) as c:
+                    schema=schema,
+                    **create_kwargs) as c:
         c.writerecords(records)
     yield path
     shutil.rmtree(tmpdir)


=====================================
tests/test_transform.py
=====================================
@@ -70,3 +70,15 @@ def test_axis_ordering(crs):
     geom = {"type": "Point", "coordinates": [-8427998.647958742, 4587905.27136252]}
     g2 = transform.transform_geom("epsg:3857", crs, geom, precision=3)
     assert g2["coordinates"] == pytest.approx(rev_expected)
+
+
+def test_transform_issue971():
+    """ See https://github.com/Toblerity/Fiona/issues/971 """
+    source_crs = "epsg:25832"
+    dest_src = "epsg:4326"
+    geom = {'type': 'GeometryCollection', 'geometries': [{'type': 'LineString',
+                                                          'coordinates': [(512381.8870945257, 5866313.311218272),
+                                                                          (512371.23869999964, 5866322.282500001),
+                                                                          (512364.6014999999, 5866328.260199999)]}]}
+    geom_transformed = transform.transform_geom(source_crs, dest_src, geom, precision=3)
+    assert geom_transformed['geometries'][0]['coordinates'][0] == pytest.approx((9.184, 52.946))



View it on GitLab: https://salsa.debian.org/debian-gis-team/fiona/-/commit/1c7d94a6021856b030e59077462586bb31bdf6f0

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/fiona/-/commit/1c7d94a6021856b030e59077462586bb31bdf6f0
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20201118/fa6048d1/attachment-0001.html>


More information about the Pkg-grass-devel mailing list