[fiona] 08/10: Drop patches applied/included upstream. Refresh remaining patches.

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sat Jun 11 12:40:42 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository fiona.

commit bebe62999f6e9b06a11e68086c8b1a661add1c65
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Jun 11 12:50:52 2016 +0200

    Drop patches applied/included upstream. Refresh remaining patches.
---
 debian/changelog                                   |    1 +
 ...-fio-command-to-fiona-to-avoid-name-clash.patch |    2 +-
 debian/patches/0003-GDAL-2.0.patch                 | 4582 --------------------
 .../0004-Just-use-int-as-a-plain-old-builtin.patch |   36 -
 ...at-fiona.remove-for-deleting-data-sources.patch |  246 --
 .../0006-Remove-unknown-distribution-options.patch |    2 +-
 debian/patches/0007-clean.patch                    |  123 -
 .../patches/0008-Disable-GDAL-2-ImportError.patch  |   20 -
 debian/patches/series                              |    5 -
 9 files changed, 3 insertions(+), 5014 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 81a44ed..88e3e01 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,6 +5,7 @@ fiona (1.7~b1-1) UNRELEASED; urgency=medium
   * Override dh_auto_test to ignore test failures on Hurd & kFreeBSD.
   * Update watch file to handle pre-releases.
   * Add python{,3}-munch to build dependencies.
+  * Drop patches applied/included upstream. Refresh remaining patches.
 
  -- Bas Couwenberg <sebastic at debian.org>  Sat, 11 Jun 2016 12:40:06 +0200
 
diff --git a/debian/patches/0001-Rename-fio-command-to-fiona-to-avoid-name-clash.patch b/debian/patches/0001-Rename-fio-command-to-fiona-to-avoid-name-clash.patch
index fdd825b..f00002b 100644
--- a/debian/patches/0001-Rename-fio-command-to-fiona-to-avoid-name-clash.patch
+++ b/debian/patches/0001-Rename-fio-command-to-fiona-to-avoid-name-clash.patch
@@ -9,7 +9,7 @@ There is already another package providing a binary "fio" (fio).
 
 --- a/setup.py
 +++ b/setup.py
-@@ -181,7 +181,7 @@ setup_args = dict(
+@@ -198,7 +198,7 @@ setup_args = dict(
      packages=['fiona', 'fiona.fio'],
      entry_points='''
          [console_scripts]
diff --git a/debian/patches/0003-GDAL-2.0.patch b/debian/patches/0003-GDAL-2.0.patch
deleted file mode 100644
index 2c173e6..0000000
--- a/debian/patches/0003-GDAL-2.0.patch
+++ /dev/null
@@ -1,4582 +0,0 @@
-Origin: https://github.com/Toblerity/Fiona/commit/3ebef78f2d1af1e306ad2a1df043511bfc55c13b
-Bug: https://github.com/Toblerity/Fiona/issues/239
-Bug-Debian: https://bugs.debian.org/802808
-From 84e7ce2786e3d881d0a88156bb1e26167bb2ce0d Mon Sep 17 00:00:00 2001
-From: Rene Buffat <buffat at gmail.com>
-Date: Wed, 23 Sep 2015 22:40:37 +0200
-Subject: [PATCH 01/16] sperate implementation for gdal2
-
----
- .travis.yml       |    2 +-
- fiona/ograpi.pxd  |  145 --
- fiona/ograpi1.pxd |  145 ++
- fiona/ograpi2.pxd |  183 ++
- fiona/ogrext.pyx  | 1233 -----------
- fiona/ogrext1.pyx | 1233 +++++++++++
- fiona/ogrext2.pyx | 6240 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- setup.py          |   14 +-
- 8 files changed, 7814 insertions(+), 1381 deletions(-)
- delete mode 100644 fiona/ograpi.pxd
- create mode 100644 fiona/ograpi1.pxd
- create mode 100644 fiona/ograpi2.pxd
- delete mode 100644 fiona/ogrext.pyx
- create mode 100644 fiona/ogrext1.pyx
- create mode 100644 fiona/ogrext2.pyx
-
---- a/.travis.yml
-+++ b/.travis.yml
-@@ -8,6 +8,7 @@ before_install:
-   - sudo apt-get update -qq
-   - sudo apt-get install -y libgdal1h gdal-bin libgdal-dev
- install:
-+  - "pip install -r requirements.txt"
-   - "pip install -r requirements-dev.txt"
-   - "pip install pytest"
-   - "pip install coveralls"
---- a/fiona/ograpi.pxd
-+++ /dev/null
-@@ -1,145 +0,0 @@
--# Copyright (c) 2007, Sean C. Gillies
--# All rights reserved.
--# See ../LICENSE.txt
--
--cdef extern from "gdal.h":
--    char * GDALVersionInfo (char *pszRequest)
--
--cdef extern from "gdal_version.h":
--    int    GDAL_COMPUTE_VERSION(int maj, int min, int rev)
--
--cdef extern from "cpl_conv.h":
--    void *  CPLMalloc (size_t)
--    void    CPLFree (void *ptr)
--    void    CPLSetThreadLocalConfigOption (char *key, char *val)
--    const char *CPLGetConfigOption (char *, char *)
--
--cdef extern from "cpl_string.h":
--    char ** CSLSetNameValue (char **list, char *name, char *value)
--    void    CSLDestroy (char **list)
--
--cdef extern from "cpl_vsi.h":
--    ctypedef struct VSILFILE:
--        pass
--    int VSIFCloseL (VSILFILE *)
--    VSILFILE * VSIFileFromMemBuffer (const char * filename,
--                                     unsigned char * data,
--                                     int data_len,
--                                     int take_ownership)
--    int VSIUnlink (const char * pathname)
--
--ctypedef int OGRErr
--ctypedef struct OGREnvelope:
--    double MinX
--    double MaxX
--    double MinY
--    double MaxY
--
--cdef extern from "ogr_core.h":
--    char *  OGRGeometryTypeToName(int)
--
--cdef extern from "ogr_srs_api.h":
--    void    OSRCleanup ()
--    void *  OSRClone (void *srs)
--    void    OSRDestroySpatialReference (void *srs)
--    int     OSRExportToProj4 (void *srs, char **params)
--    int     OSRExportToWkt (void *srs, char **params)
--    int     OSRImportFromEPSG (void *srs, int code)
--    int     OSRImportFromProj4 (void *srs, char *proj)
--    int     OSRSetFromUserInput (void *srs, char *input)
--    int     OSRAutoIdentifyEPSG (void *srs)
--    int     OSRFixup(void *srs)
--    const char * OSRGetAuthorityName (void *srs, const char *key)
--    const char * OSRGetAuthorityCode (void *srs, const char *key)
--    void *  OSRNewSpatialReference (char *wkt)
--    void    OSRRelease (void *srs)
--    void *  OCTNewCoordinateTransformation (void *source, void *dest)
--    void    OCTDestroyCoordinateTransformation (void *source)
--    int     OCTTransform (void *ct, int nCount, double *x, double *y, double *z)
--
--cdef extern from "ogr_api.h":
--    char *  OGR_Dr_GetName (void *driver)
--    void *  OGR_Dr_CreateDataSource (void *driver, const char *path, char **options)
--    int     OGR_Dr_DeleteDataSource (void *driver, char *)
--    void *  OGR_Dr_Open (void *driver, const char *path, int bupdate)
--    int     OGR_DS_DeleteLayer (void *datasource, int n)
--    void *  OGR_DS_CreateLayer (void *datasource, char *name, void *crs, int geomType, char **options)
--    void *  OGR_DS_ExecuteSQL (void *datasource, char *name, void *filter, char *dialext)
--    void    OGR_DS_Destroy (void *datasource)
--    void *  OGR_DS_GetDriver (void *layer_defn)
--    void *  OGR_DS_GetLayerByName (void *datasource, char *name)
--    int     OGR_DS_GetLayerCount (void *datasource)
--    void *  OGR_DS_GetLayer (void *datasource, int n)
--    void    OGR_DS_ReleaseResultSet (void *datasource, void *results)
--    int     OGR_DS_SyncToDisk (void *datasource)
--    void *  OGR_F_Create (void *featuredefn)
--    void    OGR_F_Destroy (void *feature)
--    long    OGR_F_GetFID (void *feature)
--    int     OGR_F_IsFieldSet (void *feature, int n)
--    int     OGR_F_GetFieldAsDateTime (void *feature, int n, int *y, int *m, int *d, int *h, int *m, int *s, int *z)
--    double  OGR_F_GetFieldAsDouble (void *feature, int n)
--    int     OGR_F_GetFieldAsInteger (void *feature, int n)
--    char *  OGR_F_GetFieldAsString (void *feature, int n)
--    int     OGR_F_GetFieldCount (void *feature)
--    void *  OGR_F_GetFieldDefnRef (void *feature, int n)
--    int     OGR_F_GetFieldIndex (void *feature, char *name)
--    void *  OGR_F_GetGeometryRef (void *feature)
--    void    OGR_F_SetFieldDateTime (void *feature, int n, int y, int m, int d, int hh, int mm, int ss, int tz)
--    void    OGR_F_SetFieldDouble (void *feature, int n, double value)
--    void    OGR_F_SetFieldInteger (void *feature, int n, int value)
--    void    OGR_F_SetFieldString (void *feature, int n, char *value)
--    int     OGR_F_SetGeometryDirectly (void *feature, void *geometry)
--    void *  OGR_FD_Create (char *name)
--    int     OGR_FD_GetFieldCount (void *featuredefn)
--    void *  OGR_FD_GetFieldDefn (void *featuredefn, int n)
--    int     OGR_FD_GetGeomType (void *featuredefn)
--    char *  OGR_FD_GetName (void *featuredefn)
--    void *  OGR_Fld_Create (char *name, int fieldtype)
--    void    OGR_Fld_Destroy (void *fielddefn)
--    char *  OGR_Fld_GetNameRef (void *fielddefn)
--    int     OGR_Fld_GetPrecision (void *fielddefn)
--    int     OGR_Fld_GetType (void *fielddefn)
--    int     OGR_Fld_GetWidth (void *fielddefn)
--    void    OGR_Fld_Set (void *fielddefn, char *name, int fieldtype, int width, int precision, int justification)
--    void    OGR_Fld_SetPrecision (void *fielddefn, int n)
--    void    OGR_Fld_SetWidth (void *fielddefn, int n)
--    OGRErr  OGR_G_AddGeometryDirectly (void *geometry, void *part)
--    void    OGR_G_AddPoint (void *geometry, double x, double y, double z)
--    void    OGR_G_AddPoint_2D (void *geometry, double x, double y)
--    void    OGR_G_CloseRings (void *geometry)
--    void *  OGR_G_CreateGeometry (int wkbtypecode)
--    void    OGR_G_DestroyGeometry (void *geometry)
--    unsigned char *  OGR_G_ExportToJson (void *geometry)
--    void    OGR_G_ExportToWkb (void *geometry, int endianness, char *buffer)
--    int     OGR_G_GetCoordinateDimension (void *geometry)
--    int     OGR_G_GetGeometryCount (void *geometry)
--    unsigned char *  OGR_G_GetGeometryName (void *geometry)
--    int     OGR_G_GetGeometryType (void *geometry)
--    void *  OGR_G_GetGeometryRef (void *geometry, int n)
--    int     OGR_G_GetPointCount (void *geometry)
--    double  OGR_G_GetX (void *geometry, int n)
--    double  OGR_G_GetY (void *geometry, int n)
--    double  OGR_G_GetZ (void *geometry, int n)
--    void    OGR_G_ImportFromWkb (void *geometry, unsigned char *bytes, int nbytes)
--    int     OGR_G_WkbSize (void *geometry)
--    OGRErr  OGR_L_CreateFeature (void *layer, void *feature)
--    int     OGR_L_CreateField (void *layer, void *fielddefn, int flexible)
--    OGRErr  OGR_L_GetExtent (void *layer, void *extent, int force)
--    void *  OGR_L_GetFeature (void *layer, int n)
--    int     OGR_L_GetFeatureCount (void *layer, int m)
--    void *  OGR_L_GetLayerDefn (void *layer)
--    char *  OGR_L_GetName (void *layer)
--    void *  OGR_L_GetNextFeature (void *layer)
--    void *  OGR_L_GetSpatialFilter (void *layer)
--    void *  OGR_L_GetSpatialRef (void *layer)
--    void    OGR_L_ResetReading (void *layer)
--    void    OGR_L_SetSpatialFilter (void *layer, void *geometry)
--    void    OGR_L_SetSpatialFilterRect (
--                void *layer, double minx, double miny, double maxx, double maxy
--                )
--    int     OGR_L_TestCapability (void *layer, char *name)
--    void *  OGRGetDriverByName (char *)
--    void *  OGROpen (char *path, int mode, void *x)
--    void *  OGROpenShared (char *path, int mode, void *x)
--    int     OGRReleaseDataSource (void *datasource)
--    OGRErr  OGR_L_SetNextByIndex (void *layer, long nIndex)
---- /dev/null
-+++ b/fiona/ograpi1.pxd
-@@ -0,0 +1,145 @@
-+# Copyright (c) 2007, Sean C. Gillies
-+# All rights reserved.
-+# See ../LICENSE.txt
-+
-+cdef extern from "gdal.h":
-+    char * GDALVersionInfo (char *pszRequest)
-+
-+cdef extern from "gdal_version.h":
-+    int    GDAL_COMPUTE_VERSION(int maj, int min, int rev)
-+
-+cdef extern from "cpl_conv.h":
-+    void *  CPLMalloc (size_t)
-+    void    CPLFree (void *ptr)
-+    void    CPLSetThreadLocalConfigOption (char *key, char *val)
-+    const char *CPLGetConfigOption (char *, char *)
-+
-+cdef extern from "cpl_string.h":
-+    char ** CSLSetNameValue (char **list, char *name, char *value)
-+    void    CSLDestroy (char **list)
-+
-+cdef extern from "cpl_vsi.h":
-+    ctypedef struct VSILFILE:
-+        pass
-+    int VSIFCloseL (VSILFILE *)
-+    VSILFILE * VSIFileFromMemBuffer (const char * filename,
-+                                     unsigned char * data,
-+                                     int data_len,
-+                                     int take_ownership)
-+    int VSIUnlink (const char * pathname)
-+
-+ctypedef int OGRErr
-+ctypedef struct OGREnvelope:
-+    double MinX
-+    double MaxX
-+    double MinY
-+    double MaxY
-+
-+cdef extern from "ogr_core.h":
-+    char *  OGRGeometryTypeToName(int)
-+
-+cdef extern from "ogr_srs_api.h":
-+    void    OSRCleanup ()
-+    void *  OSRClone (void *srs)
-+    void    OSRDestroySpatialReference (void *srs)
-+    int     OSRExportToProj4 (void *srs, char **params)
-+    int     OSRExportToWkt (void *srs, char **params)
-+    int     OSRImportFromEPSG (void *srs, int code)
-+    int     OSRImportFromProj4 (void *srs, char *proj)
-+    int     OSRSetFromUserInput (void *srs, char *input)
-+    int     OSRAutoIdentifyEPSG (void *srs)
-+    int     OSRFixup(void *srs)
-+    const char * OSRGetAuthorityName (void *srs, const char *key)
-+    const char * OSRGetAuthorityCode (void *srs, const char *key)
-+    void *  OSRNewSpatialReference (char *wkt)
-+    void    OSRRelease (void *srs)
-+    void *  OCTNewCoordinateTransformation (void *source, void *dest)
-+    void    OCTDestroyCoordinateTransformation (void *source)
-+    int     OCTTransform (void *ct, int nCount, double *x, double *y, double *z)
-+
-+cdef extern from "ogr_api.h":
-+    char *  OGR_Dr_GetName (void *driver)
-+    void *  OGR_Dr_CreateDataSource (void *driver, const char *path, char **options)
-+    int     OGR_Dr_DeleteDataSource (void *driver, char *)
-+    void *  OGR_Dr_Open (void *driver, const char *path, int bupdate)
-+    int     OGR_DS_DeleteLayer (void *datasource, int n)
-+    void *  OGR_DS_CreateLayer (void *datasource, char *name, void *crs, int geomType, char **options)
-+    void *  OGR_DS_ExecuteSQL (void *datasource, char *name, void *filter, char *dialext)
-+    void    OGR_DS_Destroy (void *datasource)
-+    void *  OGR_DS_GetDriver (void *layer_defn)
-+    void *  OGR_DS_GetLayerByName (void *datasource, char *name)
-+    int     OGR_DS_GetLayerCount (void *datasource)
-+    void *  OGR_DS_GetLayer (void *datasource, int n)
-+    void    OGR_DS_ReleaseResultSet (void *datasource, void *results)
-+    int     OGR_DS_SyncToDisk (void *datasource)
-+    void *  OGR_F_Create (void *featuredefn)
-+    void    OGR_F_Destroy (void *feature)
-+    long    OGR_F_GetFID (void *feature)
-+    int     OGR_F_IsFieldSet (void *feature, int n)
-+    int     OGR_F_GetFieldAsDateTime (void *feature, int n, int *y, int *m, int *d, int *h, int *m, int *s, int *z)
-+    double  OGR_F_GetFieldAsDouble (void *feature, int n)
-+    int     OGR_F_GetFieldAsInteger (void *feature, int n)
-+    char *  OGR_F_GetFieldAsString (void *feature, int n)
-+    int     OGR_F_GetFieldCount (void *feature)
-+    void *  OGR_F_GetFieldDefnRef (void *feature, int n)
-+    int     OGR_F_GetFieldIndex (void *feature, char *name)
-+    void *  OGR_F_GetGeometryRef (void *feature)
-+    void    OGR_F_SetFieldDateTime (void *feature, int n, int y, int m, int d, int hh, int mm, int ss, int tz)
-+    void    OGR_F_SetFieldDouble (void *feature, int n, double value)
-+    void    OGR_F_SetFieldInteger (void *feature, int n, int value)
-+    void    OGR_F_SetFieldString (void *feature, int n, char *value)
-+    int     OGR_F_SetGeometryDirectly (void *feature, void *geometry)
-+    void *  OGR_FD_Create (char *name)
-+    int     OGR_FD_GetFieldCount (void *featuredefn)
-+    void *  OGR_FD_GetFieldDefn (void *featuredefn, int n)
-+    int     OGR_FD_GetGeomType (void *featuredefn)
-+    char *  OGR_FD_GetName (void *featuredefn)
-+    void *  OGR_Fld_Create (char *name, int fieldtype)
-+    void    OGR_Fld_Destroy (void *fielddefn)
-+    char *  OGR_Fld_GetNameRef (void *fielddefn)
-+    int     OGR_Fld_GetPrecision (void *fielddefn)
-+    int     OGR_Fld_GetType (void *fielddefn)
-+    int     OGR_Fld_GetWidth (void *fielddefn)
-+    void    OGR_Fld_Set (void *fielddefn, char *name, int fieldtype, int width, int precision, int justification)
-+    void    OGR_Fld_SetPrecision (void *fielddefn, int n)
-+    void    OGR_Fld_SetWidth (void *fielddefn, int n)
-+    OGRErr  OGR_G_AddGeometryDirectly (void *geometry, void *part)
-+    void    OGR_G_AddPoint (void *geometry, double x, double y, double z)
-+    void    OGR_G_AddPoint_2D (void *geometry, double x, double y)
-+    void    OGR_G_CloseRings (void *geometry)
-+    void *  OGR_G_CreateGeometry (int wkbtypecode)
-+    void    OGR_G_DestroyGeometry (void *geometry)
-+    unsigned char *  OGR_G_ExportToJson (void *geometry)
-+    void    OGR_G_ExportToWkb (void *geometry, int endianness, char *buffer)
-+    int     OGR_G_GetCoordinateDimension (void *geometry)
-+    int     OGR_G_GetGeometryCount (void *geometry)
-+    unsigned char *  OGR_G_GetGeometryName (void *geometry)
-+    int     OGR_G_GetGeometryType (void *geometry)
-+    void *  OGR_G_GetGeometryRef (void *geometry, int n)
-+    int     OGR_G_GetPointCount (void *geometry)
-+    double  OGR_G_GetX (void *geometry, int n)
-+    double  OGR_G_GetY (void *geometry, int n)
-+    double  OGR_G_GetZ (void *geometry, int n)
-+    void    OGR_G_ImportFromWkb (void *geometry, unsigned char *bytes, int nbytes)
-+    int     OGR_G_WkbSize (void *geometry)
-+    OGRErr  OGR_L_CreateFeature (void *layer, void *feature)
-+    int     OGR_L_CreateField (void *layer, void *fielddefn, int flexible)
-+    OGRErr  OGR_L_GetExtent (void *layer, void *extent, int force)
-+    void *  OGR_L_GetFeature (void *layer, int n)
-+    int     OGR_L_GetFeatureCount (void *layer, int m)
-+    void *  OGR_L_GetLayerDefn (void *layer)
-+    char *  OGR_L_GetName (void *layer)
-+    void *  OGR_L_GetNextFeature (void *layer)
-+    void *  OGR_L_GetSpatialFilter (void *layer)
-+    void *  OGR_L_GetSpatialRef (void *layer)
-+    void    OGR_L_ResetReading (void *layer)
-+    void    OGR_L_SetSpatialFilter (void *layer, void *geometry)
-+    void    OGR_L_SetSpatialFilterRect (
-+                void *layer, double minx, double miny, double maxx, double maxy
-+                )
-+    int     OGR_L_TestCapability (void *layer, char *name)
-+    void *  OGRGetDriverByName (char *)
-+    void *  OGROpen (char *path, int mode, void *x)
-+    void *  OGROpenShared (char *path, int mode, void *x)
-+    int     OGRReleaseDataSource (void *datasource)
-+    OGRErr  OGR_L_SetNextByIndex (void *layer, long nIndex)
---- /dev/null
-+++ b/fiona/ograpi2.pxd
-@@ -0,0 +1,185 @@
-+# Copyright (c) 2007, Sean C. Gillies
-+# All rights reserved.
-+# See ../LICENSE.txt
-+
-+cdef extern from "gdal.h":
-+    char * GDALVersionInfo (char *pszRequest)
-+    void * GDALGetDriverByName(const char * pszName)
-+    void * GDALOpenEx(const char * pszFilename,
-+                      unsigned int nOpenFlags,
-+                      const char ** papszAllowedDrivers,
-+                      const char ** papszOpenOptions,
-+                      const char *const *papszSibling1Files
-+                      )
-+    int GDAL_OF_UPDATE
-+    int GDAL_OF_READONLY
-+    int GDAL_OF_VECTOR
-+    int GDAL_OF_VERBOSE_ERROR
-+    int GDALDatasetGetLayerCount(void * hds)
-+    void * GDALDatasetGetLayer(void * hDS, int iLayer)
-+    void * GDALDatasetGetLayerByName(void * hDS, char * pszName)
-+    void GDALClose(void * hDS)
-+    void * GDALGetDatasetDriver(void * hDataset)
-+    void * GDALCreate(void * hDriver,
-+                      const char * pszFilename,
-+                      int nXSize,
-+                      int     nYSize,
-+                      int     nBands,
-+                      GDALDataType eBandType,
-+                      char ** papszOptions)
-+    void * GDALDatasetCreateLayer(void * hDS,
-+                                  const char * pszName,
-+                                  void * hSpatialRef,
-+                                  int eType,
-+                                  char ** papszOptions)
-+    int GDALDatasetDeleteLayer(void * hDS, int iLayer)
-+    void GDALFlushCache(void * hDS)
-+    char * GDALGetDriverShortName(void * hDriver)
-+    char * GDALGetDatasetDriver (void * hDataset)
-+
-+
-+    ctypedef enum GDALDataType:
-+        GDT_Unknown
-+        GDT_Byte
-+        GDT_UInt16
-+        GDT_Int16
-+        GDT_UInt32
-+        GDT_Int32
-+        GDT_Float32
-+        GDT_Float64
-+        GDT_CInt16
-+        GDT_CInt32
-+        GDT_CFloat32
-+        GDT_CFloat64
-+        GDT_TypeCount
-+
-+cdef extern from "gdal_version.h":
-+    int    GDAL_COMPUTE_VERSION(int maj, int min, int rev)
-+
-+cdef extern from "cpl_conv.h":
-+    void *  CPLMalloc (size_t)
-+    void    CPLFree (void *ptr)
-+    void    CPLSetThreadLocalConfigOption (char *key, char *val)
-+    const char *CPLGetConfigOption (char *, char *)
-+
-+cdef extern from "cpl_string.h":
-+    char ** CSLSetNameValue (char **list, char *name, char *value)
-+    void    CSLDestroy (char **list)
-+
-+cdef extern from "cpl_vsi.h":
-+    ctypedef struct VSILFILE:
-+        pass
-+    int VSIFCloseL (VSILFILE *)
-+    VSILFILE * VSIFileFromMemBuffer (const char * filename,
-+                                     unsigned char * data,
-+                                     int data_len,
-+                                     int take_ownership)
-+    int VSIUnlink (const char * pathname)
-+
-+ctypedef int OGRErr
-+ctypedef struct OGREnvelope:
-+    double MinX
-+    double MaxX
-+    double MinY
-+    double MaxY
-+
-+cdef extern from "ogr_core.h":
-+    char *  OGRGeometryTypeToName(int)
-+
-+cdef extern from "ogr_srs_api.h":
-+    void    OSRCleanup ()
-+    void *  OSRClone (void *srs)
-+    void    OSRDestroySpatialReference (void *srs)
-+    int     OSRExportToProj4 (void *srs, char **params)
-+    int     OSRExportToWkt (void *srs, char **params)
-+    int     OSRImportFromEPSG (void *srs, int code)
-+    int     OSRImportFromProj4 (void *srs, char *proj)
-+    int     OSRSetFromUserInput (void *srs, char *input)
-+    int     OSRAutoIdentifyEPSG (void *srs)
-+    int     OSRFixup(void *srs)
-+    const char * OSRGetAuthorityName (void *srs, const char *key)
-+    const char * OSRGetAuthorityCode (void *srs, const char *key)
-+    void *  OSRNewSpatialReference (char *wkt)
-+    void    OSRRelease (void *srs)
-+    void *  OCTNewCoordinateTransformation (void *source, void *dest)
-+    void    OCTDestroyCoordinateTransformation (void *source)
-+    int     OCTTransform (void *ct, int nCount, double *x, double *y, double *z)
-+
-+cdef extern from "ogr_api.h":
-+    char *  OGR_Dr_GetName (void *driver)
-+    void *  OGR_Dr_CreateDataSource (void *driver, const char *path, char **options)
-+    int     OGR_Dr_DeleteDataSource (void *driver, char *)
-+    void *  OGR_Dr_Open (void *driver, const char *path, int bupdate)
-+    void *  OGR_F_Create (void *featuredefn)
-+    void    OGR_F_Destroy (void *feature)
-+    long    OGR_F_GetFID (void *feature)
-+    int     OGR_F_IsFieldSet (void *feature, int n)
-+    int     OGR_F_GetFieldAsDateTime (void *feature, int n, int *y, int *m, int *d, int *h, int *m, int *s, int *z)
-+    double  OGR_F_GetFieldAsDouble (void *feature, int n)
-+    int     OGR_F_GetFieldAsInteger (void *feature, int n)
-+    char *  OGR_F_GetFieldAsString (void *feature, int n)
-+    int     OGR_F_GetFieldCount (void *feature)
-+    void *  OGR_F_GetFieldDefnRef (void *feature, int n)
-+    int     OGR_F_GetFieldIndex (void *feature, char *name)
-+    void *  OGR_F_GetGeometryRef (void *feature)
-+    void    OGR_F_SetFieldDateTime (void *feature, int n, int y, int m, int d, int hh, int mm, int ss, int tz)
-+    void    OGR_F_SetFieldDouble (void *feature, int n, double value)
-+    void    OGR_F_SetFieldInteger (void *feature, int n, int value)
-+    void    OGR_F_SetFieldString (void *feature, int n, char *value)
-+    int     OGR_F_SetGeometryDirectly (void *feature, void *geometry)
-+    void *  OGR_FD_Create (char *name)
-+    int     OGR_FD_GetFieldCount (void *featuredefn)
-+    void *  OGR_FD_GetFieldDefn (void *featuredefn, int n)
-+    int     OGR_FD_GetGeomType (void *featuredefn)
-+    char *  OGR_FD_GetName (void *featuredefn)
-+    void *  OGR_Fld_Create (char *name, int fieldtype)
-+    void    OGR_Fld_Destroy (void *fielddefn)
-+    char *  OGR_Fld_GetNameRef (void *fielddefn)
-+    int     OGR_Fld_GetPrecision (void *fielddefn)
-+    int     OGR_Fld_GetType (void *fielddefn)
-+    int     OGR_Fld_GetWidth (void *fielddefn)
-+    void    OGR_Fld_Set (void *fielddefn, char *name, int fieldtype, int width, int precision, int justification)
-+    void    OGR_Fld_SetPrecision (void *fielddefn, int n)
-+    void    OGR_Fld_SetWidth (void *fielddefn, int n)
-+    OGRErr  OGR_G_AddGeometryDirectly (void *geometry, void *part)
-+    void    OGR_G_AddPoint (void *geometry, double x, double y, double z)
-+    void    OGR_G_AddPoint_2D (void *geometry, double x, double y)
-+    void    OGR_G_CloseRings (void *geometry)
-+    void *  OGR_G_CreateGeometry (int wkbtypecode)
-+    void    OGR_G_DestroyGeometry (void *geometry)
-+    unsigned char *  OGR_G_ExportToJson (void *geometry)
-+    void    OGR_G_ExportToWkb (void *geometry, int endianness, char *buffer)
-+    int     OGR_G_GetCoordinateDimension (void *geometry)
-+    int     OGR_G_GetGeometryCount (void *geometry)
-+    unsigned char *  OGR_G_GetGeometryName (void *geometry)
-+    int     OGR_G_GetGeometryType (void *geometry)
-+    void *  OGR_G_GetGeometryRef (void *geometry, int n)
-+    int     OGR_G_GetPointCount (void *geometry)
-+    double  OGR_G_GetX (void *geometry, int n)
-+    double  OGR_G_GetY (void *geometry, int n)
-+    double  OGR_G_GetZ (void *geometry, int n)
-+    void    OGR_G_ImportFromWkb (void *geometry, unsigned char *bytes, int nbytes)
-+    int     OGR_G_WkbSize (void *geometry)
-+    OGRErr  OGR_L_CreateFeature (void *layer, void *feature)
-+    int     OGR_L_CreateField (void *layer, void *fielddefn, int flexible)
-+    OGRErr  OGR_L_GetExtent (void *layer, void *extent, int force)
-+    void *  OGR_L_GetFeature (void *layer, int n)
-+    int     OGR_L_GetFeatureCount (void *layer, int m)
-+    void *  OGR_L_GetLayerDefn (void *layer)
-+    char *  OGR_L_GetName (void *layer)
-+    void *  OGR_L_GetNextFeature (void *layer)
-+    void *  OGR_L_GetSpatialFilter (void *layer)
-+    void *  OGR_L_GetSpatialRef (void *layer)
-+    void    OGR_L_ResetReading (void *layer)
-+    void    OGR_L_SetSpatialFilter (void *layer, void *geometry)
-+    void    OGR_L_SetSpatialFilterRect (
-+                void *layer, double minx, double miny, double maxx, double maxy
-+                )
-+    int     OGR_L_TestCapability (void *layer, char *name)
-+    void *  OGRGetDriverByName (char *)
-+    void *  OGROpen (char *path, int mode, void *x)
-+    void *  OGROpenShared (char *path, int mode, void *x)
-+    int     OGRReleaseDataSource (void *datasource)
-+    OGRErr  OGR_L_SetNextByIndex (void *layer, long nIndex)
-+    long long OGR_F_GetFieldAsInteger64 (void *feature, int n)
-+    void    OGR_F_SetFieldInteger64 (void *feature, int n, long long value)
---- a/fiona/ogrext.pyx
-+++ /dev/null
-@@ -1,1245 +0,0 @@
--# These are extension functions and classes using the OGR C API.
--
--import datetime
--import json
--import locale
--import logging
--import os
--import sys
--import warnings
--import math
--import uuid
--
--from six import integer_types, string_types, text_type
--
--from fiona cimport ograpi
--from fiona._geometry cimport GeomBuilder, OGRGeomBuilder
--from fiona._err import cpl_errs
--from fiona._geometry import GEOMETRY_TYPES
--from fiona.errors import (
--    DriverError, SchemaError, CRSError, FionaValueError, FieldNameEncodeError,
--    StringFieldEncodeError, StringFieldDecodeError)
--from fiona.odict import OrderedDict
--from fiona.rfc3339 import parse_date, parse_datetime, parse_time
--from fiona.rfc3339 import FionaDateType, FionaDateTimeType, FionaTimeType
--
--
--log = logging.getLogger("Fiona")
--class NullHandler(logging.Handler):
--    def emit(self, record):
--        pass
--log.addHandler(NullHandler())
--
--
--# Mapping of OGR integer field types to Fiona field type names.
--#
--# Lists are currently unsupported in this version, but might be done as
--# arrays in a future version.
--
--FIELD_TYPES = [
--    'int',          # OFTInteger, Simple 32bit integer
--    None,           # OFTIntegerList, List of 32bit integers
--    'float',        # OFTReal, Double Precision floating point
--    None,           # OFTRealList, List of doubles
--    'str',          # OFTString, String of ASCII chars
--    None,           # OFTStringList, Array of strings
--    None,           # OFTWideString, deprecated
--    None,           # OFTWideStringList, deprecated
--    None,           # OFTBinary, Raw Binary data
--    'date',         # OFTDate, Date
--    'time',         # OFTTime, Time
--    'datetime',     # OFTDateTime, Date and Time
--    'int',          # OFTInteger64, Single 64bit integer #Not supported
--    None,           # OFTInteger64List, List of 64bit integers #Not supported
--    ]
--
--# Mapping of Fiona field type names to Python types.
--FIELD_TYPES_MAP = {
--    'int':      int,
--    'float':    float,
--    'str':      text_type,
--    'date':     FionaDateType,
--    'time':     FionaTimeType,
--    'datetime': FionaDateTimeType
--   }
--
--# OGR Layer capability
--OLC_RANDOMREAD = b"RandomRead"
--OLC_SEQUENTIALWRITE = b"SequentialWrite"
--OLC_RANDOMWRITE = b"RandomWrite"
--OLC_FASTSPATIALFILTER = b"FastSpatialFilter"
--OLC_FASTFEATURECOUNT = b"FastFeatureCount"
--OLC_FASTGETEXTENT = b"FastGetExtent"
--OLC_FASTSETNEXTBYINDEX = b"FastSetNextByIndex"
--OLC_CREATEFIELD = b"CreateField"
--OLC_CREATEGEOMFIELD = b"CreateGeomField"
--OLC_DELETEFIELD = b"DeleteField"
--OLC_REORDERFIELDS = b"ReorderFields"
--OLC_ALTERFIELDDEFN = b"AlterFieldDefn"
--OLC_DELETEFEATURE = b"DeleteFeature"
--OLC_STRINGSASUTF8 = b"StringsAsUTF8"
--OLC_TRANSACTIONS = b"Transactions"
--
--# OGR integer error types.
--
--OGRERR_NONE = 0
--OGRERR_NOT_ENOUGH_DATA = 1    # not enough data to deserialize */
--OGRERR_NOT_ENOUGH_MEMORY = 2
--OGRERR_UNSUPPORTED_GEOMETRY_TYPE = 3
--OGRERR_UNSUPPORTED_OPERATION = 4
--OGRERR_CORRUPT_DATA = 5
--OGRERR_FAILURE = 6
--OGRERR_UNSUPPORTED_SRS = 7
--OGRERR_INVALID_HANDLE = 8
--
--# Recent versions of OGR can sometimes detect file encoding, but don't
--# provide access yet to the detected encoding. Hence this variable.
--OGR_DETECTED_ENCODING = '-ogr-detected-encoding'
--
--
--def _explode(coords):
--    """Explode a GeoJSON geometry's coordinates object and yield
--    coordinate tuples. As long as the input is conforming, the type of
--    the geometry doesn't matter."""
--    for e in coords:
--        if isinstance(e, (float, int)):
--            yield coords
--            break
--        else:
--            for f in _explode(e):
--                yield f
--
--
--def _bounds(geometry):
--    """Bounding box of a GeoJSON geometry"""
--    try:
--        xyz = tuple(zip(*list(_explode(geometry['coordinates']))))
--        return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1])
--    except (KeyError, TypeError):
--        return None
--
--def calc_gdal_version_num(maj, min, rev):
--    """Calculates the internal gdal version number based on major, minor and revision"""
--    return int(maj * 1000000 + min * 10000 + rev*100)
--
--def get_gdal_version_num():
--    """Return current internal version number of gdal"""
--    return int(ograpi.GDALVersionInfo("VERSION_NUM"))
--
--def get_gdal_release_name():
--    """Return release name of gdal"""
--    return ograpi.GDALVersionInfo("RELEASE_NAME")
--
--
--# Feature extension classes and functions follow.
--
--cdef class FeatureBuilder:
--    """Build Fiona features from OGR feature pointers.
--
--    No OGR objects are allocated by this function and the feature
--    argument is not destroyed.
--    """
--
--    cdef build(self, void *feature, encoding='utf-8', bbox=False, driver=None):
--        # The only method anyone ever needs to call
--        cdef void *fdefn
--        cdef int i
--        cdef int y = 0
--        cdef int m = 0
--        cdef int d = 0
--        cdef int hh = 0
--        cdef int mm = 0
--        cdef int ss = 0
--        cdef int tz = 0
--        cdef int retval
--        cdef char *key_c
--        props = OrderedDict()
--        for i in range(ograpi.OGR_F_GetFieldCount(feature)):
--            fdefn = ograpi.OGR_F_GetFieldDefnRef(feature, i)
--            if fdefn == NULL:
--                raise ValueError("Null feature definition")
--            key_c = ograpi.OGR_Fld_GetNameRef(fdefn)
--            if key_c == NULL:
--                raise ValueError("Null field name reference")
--            key_b = key_c
--            key = key_b.decode(encoding)
--            fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(fdefn)]
--            if not fieldtypename:
--                log.warn(
--                    "Skipping field %s: invalid type %s", 
--                    key,
--                    ograpi.OGR_Fld_GetType(fdefn))
--                continue
--
--            # TODO: other types
--            fieldtype = FIELD_TYPES_MAP[fieldtypename]
--            if not ograpi.OGR_F_IsFieldSet(feature, i):
--                props[key] = None
--            elif fieldtype is int:
--                props[key] = ograpi.OGR_F_GetFieldAsInteger(feature, i)
--            elif fieldtype is float:
--                props[key] = ograpi.OGR_F_GetFieldAsDouble(feature, i)
--
--            elif fieldtype is text_type:
--                try:
--                    val = ograpi.OGR_F_GetFieldAsString(feature, i)
--                    val = val.decode(encoding)
--                except UnicodeError as exc:
--                    raise StringFieldDecodeError(
--                        "Failed to decode {0} using {1} codec: {2}".format(
--                            val, encoding, str(exc)))
--
--                # Does the text contain a JSON object? Let's check.
--                # Let's check as cheaply as we can.
--                if driver == 'GeoJSON' and val.startswith('{'):
--                    try:
--                        val = json.loads(val)
--                    except ValueError as err:
--                        log.warn(str(err))
--
--                # Now add to the properties object.
--                props[key] = val
--
--            elif fieldtype in (FionaDateType, FionaTimeType, FionaDateTimeType):
--                retval = ograpi.OGR_F_GetFieldAsDateTime(
--                    feature, i, &y, &m, &d, &hh, &mm, &ss, &tz)
--                if fieldtype is FionaDateType:
--                    props[key] = datetime.date(y, m, d).isoformat()
--                elif fieldtype is FionaTimeType:
--                    props[key] = datetime.time(hh, mm, ss).isoformat()
--                else:
--                    props[key] = datetime.datetime(
--                        y, m, d, hh, mm, ss).isoformat()
--            else:
--                log.debug("%s: None, fieldtype: %r, %r" % (key, fieldtype, fieldtype in string_types))
--                props[key] = None
--
--        cdef void *cogr_geometry = ograpi.OGR_F_GetGeometryRef(feature)
--        if cogr_geometry is not NULL:
--            geom = GeomBuilder().build(cogr_geometry)
--        else:
--            geom = None
--        return {
--            'type': 'Feature',
--            'id': str(ograpi.OGR_F_GetFID(feature)),
--            'geometry': geom,
--            'properties': props }
--
--
--cdef class OGRFeatureBuilder:
--    
--    """Builds an OGR Feature from a Fiona feature mapping.
--
--    Allocates one OGR Feature which should be destroyed by the caller.
--    Borrows a layer definition from the collection.
--    """
--    
--    cdef void * build(self, feature, collection) except NULL:
--        cdef void *cogr_geometry = NULL
--        cdef char *string_c
--        cdef WritingSession session
--        session = collection.session
--        cdef void *cogr_layer = session.cogr_layer
--        if cogr_layer == NULL:
--            raise ValueError("Null layer")
--        cdef void *cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(cogr_layer)
--        if cogr_featuredefn == NULL:
--            raise ValueError("Null feature definition")
--        cdef void *cogr_feature = ograpi.OGR_F_Create(cogr_featuredefn)
--        if cogr_feature == NULL:
--            raise ValueError("Null feature")
--        
--        if feature['geometry'] is not None:
--            cogr_geometry = OGRGeomBuilder().build(
--                                feature['geometry'])
--        ograpi.OGR_F_SetGeometryDirectly(cogr_feature, cogr_geometry)
--        
--        # OGR_F_SetFieldString takes UTF-8 encoded strings ('bytes' in 
--        # Python 3).
--        encoding = session.get_internalencoding()
--
--        for key, value in feature['properties'].items():
--            log.debug(
--                "Looking up %s in %s", key, repr(session._schema_mapping))
--            ogr_key = session._schema_mapping[key]
--            schema_type = collection.schema['properties'][key]
--
--            # Catch and re-raise unicode encoding errors.
--            try:
--                key_bytes = ogr_key.encode(encoding)
--            except UnicodeError as exc:
--                raise FieldNameEncodeError(
--                    "Failed to encode {0} using {1} codec: {2}".format(
--                        key, encoding, str(exc)))
--
--            key_c = key_bytes
--            i = ograpi.OGR_F_GetFieldIndex(cogr_feature, key_c)
--            if i < 0:
--                continue
--
--            # Special case: serialize dicts to assist OGR.
--            if isinstance(value, dict):
--                value = json.dumps(value)
--
--            # Continue over the standard OGR types.
--            if isinstance(value, integer_types):
--                ograpi.OGR_F_SetFieldInteger(cogr_feature, i, value)
--            elif isinstance(value, float):
--                ograpi.OGR_F_SetFieldDouble(cogr_feature, i, value)
--            elif (isinstance(value, string_types) 
--            and schema_type in ['date', 'time', 'datetime']):
--                if schema_type == 'date':
--                    y, m, d, hh, mm, ss, ff = parse_date(value)
--                elif schema_type == 'time':
--                    y, m, d, hh, mm, ss, ff = parse_time(value)
--                else:
--                    y, m, d, hh, mm, ss, ff = parse_datetime(value)
--                ograpi.OGR_F_SetFieldDateTime(
--                    cogr_feature, i, y, m, d, hh, mm, ss, 0)
--            elif (isinstance(value, datetime.date)
--            and schema_type == 'date'):
--                y, m, d = value.year, value.month, value.day
--                ograpi.OGR_F_SetFieldDateTime(
--                    cogr_feature, i, y, m, d, 0, 0, 0, 0)
--            elif (isinstance(value, datetime.datetime)
--            and schema_type == 'datetime'):
--                y, m, d = value.year, value.month, value.day
--                hh, mm, ss = value.hour, value.minute, value.second
--                ograpi.OGR_F_SetFieldDateTime(
--                    cogr_feature, i, y, m, d, hh, mm, ss, 0)
--            elif (isinstance(value, datetime.time)
--            and schema_type == 'time'):
--                hh, mm, ss = value.hour, value.minute, value.second
--                ograpi.OGR_F_SetFieldDateTime(
--                    cogr_feature, i, 0, 0, 0, hh, mm, ss, 0)
--            elif isinstance(value, string_types):
--                
--                # Catch and re-raise string field value encoding errors.
--                try:
--                    value_bytes = value.encode(encoding)
--                except UnicodeError as exc:
--                    raise StringFieldEncodeError(
--                        "Failed to encode {0} using {1} codec: {2}".format(
--                            value, encoding, str(exc)))
--
--                string_c = value_bytes
--                ograpi.OGR_F_SetFieldString(cogr_feature, i, string_c)
--            elif value is None:
--                pass # keep field unset/null
--            else:
--                raise ValueError("Invalid field type %s" % type(value))
--            log.debug("Set field %s: %s" % (key, value))
--        return cogr_feature
--
--
--cdef _deleteOgrFeature(void *cogr_feature):
--    """Delete an OGR feature"""
--    if cogr_feature is not NULL:
--        ograpi.OGR_F_Destroy(cogr_feature)
--    cogr_feature = NULL
--
--
--def featureRT(feature, collection):
--    # For testing purposes only, leaks the JSON data
--    cdef void *cogr_feature = OGRFeatureBuilder().build(feature, collection)
--    cdef void *cogr_geometry = ograpi.OGR_F_GetGeometryRef(cogr_feature)
--    if cogr_geometry == NULL:
--        raise ValueError("Null geometry")
--    log.debug("Geometry: %s" % ograpi.OGR_G_ExportToJson(cogr_geometry))
--    encoding = collection.encoding or 'utf-8'
--    result = FeatureBuilder().build(
--        cogr_feature,
--        bbox=False,
--        encoding=encoding,
--        driver=collection.driver
--    )
--    _deleteOgrFeature(cogr_feature)
--    return result
--
--
--# Collection-related extension classes and functions
--
--cdef class Session:
--    
--    cdef void *cogr_ds
--    cdef void *cogr_layer
--    cdef object _fileencoding
--    cdef object _encoding
--    cdef object collection
--
--    def __cinit__(self):
--        self.cogr_ds = NULL
--        self.cogr_layer = NULL
--        self._fileencoding = None
--        self._encoding = None
--
--    def __dealloc__(self):
--        self.stop()
--
--    def start(self, collection):
--        cdef const char *path_c = NULL
--        cdef const char *name_c = NULL
--        cdef void *drv = NULL
--        cdef void *ds = NULL
--
--        if collection.path == '-':
--            path = '/vsistdin/'
--        else:
--            path = collection.path
--        try:
--            path_b = path.encode('utf-8')
--        except UnicodeError:
--            # Presume already a UTF-8 encoded string
--            path_b = path
--        path_c = path_b
--        
--        with cpl_errs:
--            drivers = []
--            if collection._driver:
--                drivers = [collection._driver]
--            elif collection.enabled_drivers:
--                drivers = collection.enabled_drivers
--            if drivers:
--                for name in drivers:
--                    name_b = name.encode()
--                    name_c = name_b
--                    log.debug("Trying driver: %s", name)
--                    drv = ograpi.OGRGetDriverByName(name_c)
--                    if drv != NULL:
--                        ds = ograpi.OGR_Dr_Open(drv, path_c, 0)
--                    if ds != NULL:
--                        self.cogr_ds = ds
--                        collection._driver = name
--                        break
--            else:
--                self.cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
--
--        if self.cogr_ds == NULL:
--            raise FionaValueError(
--                "No dataset found at path '%s' using drivers: %s" % (
--                    collection.path,
--                    drivers or '*'))
--        
--        if isinstance(collection.name, string_types):
--            name_b = collection.name.encode('utf-8')
--            name_c = name_b
--            self.cogr_layer = ograpi.OGR_DS_GetLayerByName(
--                                self.cogr_ds, name_c)
--        elif isinstance(collection.name, int):
--            self.cogr_layer = ograpi.OGR_DS_GetLayer(
--                                self.cogr_ds, collection.name)
--            name_c = ograpi.OGR_L_GetName(self.cogr_layer)
--            name_b = name_c
--            collection.name = name_b.decode('utf-8')
--
--        if self.cogr_layer == NULL:
--            raise ValueError("Null layer: " + repr(collection.name))
--        
--        self.collection = collection
--        
--        userencoding = self.collection.encoding
--        if userencoding:
--            ograpi.CPLSetThreadLocalConfigOption('SHAPE_ENCODING', '')
--            self._fileencoding = userencoding.upper()
--        else:
--            self._fileencoding = (
--                ograpi.OGR_L_TestCapability(
--                    self.cogr_layer, OLC_STRINGSASUTF8) and
--                OGR_DETECTED_ENCODING) or (
--                self.get_driver() == "ESRI Shapefile" and
--                'ISO-8859-1') or locale.getpreferredencoding().upper()
--
--    def stop(self):
--        self.cogr_layer = NULL
--        if self.cogr_ds is not NULL:
--            ograpi.OGR_DS_Destroy(self.cogr_ds)
--        self.cogr_ds = NULL
--
--    def get_fileencoding(self):
--        return self._fileencoding
--
--    def get_internalencoding(self):
--        if not self._encoding:
--            fileencoding = self.get_fileencoding()
--            self._encoding = (
--                ograpi.OGR_L_TestCapability(
--                    self.cogr_layer, OLC_STRINGSASUTF8) and
--                'utf-8') or fileencoding
--        return self._encoding
--
--    def get_length(self):
--        if self.cogr_layer == NULL:
--            raise ValueError("Null layer")
--        return ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
--
--    def get_driver(self):
--        cdef void *cogr_driver = ograpi.OGR_DS_GetDriver(self.cogr_ds)
--        if cogr_driver == NULL:
--            raise ValueError("Null driver")
--        cdef char *name = ograpi.OGR_Dr_GetName(cogr_driver)
--        driver_name = name
--        return driver_name.decode()
-- 
--    def get_schema(self):
--        cdef int i
--        cdef int n
--        cdef void *cogr_featuredefn
--        cdef void *cogr_fielddefn
--        cdef char *key_c
--        props = []
--        
--        if self.cogr_layer == NULL:
--            raise ValueError("Null layer")
--
--        cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(self.cogr_layer)
--        if cogr_featuredefn == NULL:
--            raise ValueError("Null feature definition")
--        n = ograpi.OGR_FD_GetFieldCount(cogr_featuredefn)
--        for i from 0 <= i < n:
--            cogr_fielddefn = ograpi.OGR_FD_GetFieldDefn(cogr_featuredefn, i)
--            if cogr_fielddefn == NULL:
--                raise ValueError("Null field definition")
--            key_c = ograpi.OGR_Fld_GetNameRef(cogr_fielddefn)
--            key_b = key_c
--            if not bool(key_b):
--                raise ValueError("Invalid field name ref: %s" % key)
--            key = key_b.decode(self.get_internalencoding())
--            fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(cogr_fielddefn)]
--            if not fieldtypename:
--                log.warn(
--                    "Skipping field %s: invalid type %s", 
--                    key,
--                    ograpi.OGR_Fld_GetType(cogr_fielddefn))
--                continue
--            val = fieldtypename
--            if fieldtypename == 'float':
--                fmt = ""
--                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
--                if width: # and width != 24:
--                    fmt = ":%d" % width
--                precision = ograpi.OGR_Fld_GetPrecision(cogr_fielddefn)
--                if precision: # and precision != 15:
--                    fmt += ".%d" % precision
--                val = "float" + fmt
--            elif fieldtypename == 'int':
--                fmt = ""
--                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
--                if width: # and width != 11:
--                    fmt = ":%d" % width
--                val = fieldtypename + fmt
--            elif fieldtypename == 'str':
--                fmt = ""
--                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
--                if width: # and width != 80:
--                    fmt = ":%d" % width
--                val = fieldtypename + fmt
--
--            props.append((key, val))
--
--        cdef unsigned int geom_type = ograpi.OGR_FD_GetGeomType(
--            cogr_featuredefn)
--        return {
--            'properties': OrderedDict(props), 
--            'geometry': GEOMETRY_TYPES[geom_type]}
--
--    def get_crs(self):
--        cdef char *proj_c = NULL
--        cdef char *auth_key = NULL
--        cdef char *auth_val = NULL
--        cdef void *cogr_crs = NULL
--        if self.cogr_layer == NULL:
--            raise ValueError("Null layer")
--        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
--        crs = {}
--        if cogr_crs is not NULL:
--            log.debug("Got coordinate system")
--
--            retval = ograpi.OSRAutoIdentifyEPSG(cogr_crs)
--            if retval > 0:
--                log.info("Failed to auto identify EPSG: %d", retval)
--            
--            auth_key = ograpi.OSRGetAuthorityName(cogr_crs, NULL)
--            auth_val = ograpi.OSRGetAuthorityCode(cogr_crs, NULL)
--
--            if auth_key != NULL and auth_val != NULL:
--                key_b = auth_key
--                key = key_b.decode('utf-8')
--                if key == 'EPSG':
--                    val_b = auth_val
--                    val = val_b.decode('utf-8')
--                    crs['init'] = "epsg:" + val
--            else:
--                ograpi.OSRExportToProj4(cogr_crs, &proj_c)
--                if proj_c == NULL:
--                    raise ValueError("Null projection")
--                proj_b = proj_c
--                log.debug("Params: %s", proj_b)
--                value = proj_b.decode()
--                value = value.strip()
--                for param in value.split():
--                    kv = param.split("=")
--                    if len(kv) == 2:
--                        k, v = kv
--                        try:
--                            v = float(v)
--                            if v % 1 == 0:
--                                v = int(v)
--                        except ValueError:
--                            # Leave v as a string
--                            pass
--                    elif len(kv) == 1:
--                        k, v = kv[0], True
--                    else:
--                        raise ValueError("Unexpected proj parameter %s" % param)
--                    k = k.lstrip("+")
--                    crs[k] = v
--
--            ograpi.CPLFree(proj_c)
--        else:
--            log.debug("Projection not found (cogr_crs was NULL)")
--        return crs
--
--    def get_crs_wkt(self):
--        cdef char *proj_c = NULL
--        if self.cogr_layer == NULL:
--            raise ValueError("Null layer")
--        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
--        crs_wkt = ""
--        if cogr_crs is not NULL:
--            log.debug("Got coordinate system")
--            ograpi.OSRExportToWkt(cogr_crs, &proj_c)
--            if proj_c == NULL:
--                raise ValueError("Null projection")
--            proj_b = proj_c
--            crs_wkt = proj_b.decode('utf-8')
--            ograpi.CPLFree(proj_c)
--        else:
--            log.debug("Projection not found (cogr_crs was NULL)")
--        return crs_wkt
--
--    def get_extent(self):
--        if self.cogr_layer == NULL:
--            raise ValueError("Null layer")
--        cdef ograpi.OGREnvelope extent
--        result = ograpi.OGR_L_GetExtent(self.cogr_layer, &extent, 1)
--        return (extent.MinX, extent.MinY, extent.MaxX, extent.MaxY)
--
--    def has_feature(self, fid):
--        """Provides access to feature data by FID.
--
--        Supports Collection.__contains__().
--        """
--        cdef void * cogr_feature
--        fid = int(fid)
--        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
--        if cogr_feature != NULL:
--            _deleteOgrFeature(cogr_feature)
--            return True
--        else:
--            return False
--
--    def get_feature(self, fid):
--        """Provides access to feature data by FID.
--
--        Supports Collection.__contains__().
--        """
--        cdef void * cogr_feature
--        fid = int(fid)
--        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
--        if cogr_feature != NULL:
--            _deleteOgrFeature(cogr_feature)
--            return True
--        else:
--            return False
--
--
--    def __getitem__(self, item):
--        cdef void * cogr_feature
--        if isinstance(item, slice):
--            itr = Iterator(self.collection, item.start, item.stop, item.step)
--            log.debug("Slice: %r", item)
--            return list(itr)
--        elif isinstance(item, int):
--            index = item
--            # from the back
--            if index < 0:
--                ftcount = ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
--                if ftcount == -1:
--                    raise IndexError(
--                        "collection's dataset does not support negative indexes")
--                index += ftcount
--            cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, index)
--            if cogr_feature == NULL:
--                return None
--            feature = FeatureBuilder().build(
--                cogr_feature,
--                bbox=False,
--                encoding=self.get_internalencoding(),
--                driver=self.collection.driver
--            )
--            _deleteOgrFeature(cogr_feature)
--            return feature
--
--
--    def isactive(self):
--        if self.cogr_layer != NULL and self.cogr_ds != NULL:
--            return 1
--        else:
--            return 0
--
--
--cdef class WritingSession(Session):
--    
--    cdef object _schema_mapping
--
--    def start(self, collection):
--        cdef void *cogr_fielddefn
--        cdef void *cogr_driver
--        cdef void *cogr_ds
--        cdef void *cogr_layer
--        cdef void *cogr_srs = NULL
--        cdef char **options = NULL
--        self.collection = collection
--        cdef char *path_c
--        cdef char *driver_c
--        cdef char *name_c
--        cdef char *proj_c
--        cdef char *fileencoding_c
--        path = collection.path
--
--        if collection.mode == 'a':
--            if os.path.exists(path):
--                try:
--                    path_b = path.encode('utf-8')
--                except UnicodeError:
--                    path_b = path
--                path_c = path_b
--                with cpl_errs:
--                    self.cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
--                if self.cogr_ds == NULL:
--                    raise RuntimeError("Failed to open %s" % path)
--                cogr_driver = ograpi.OGR_DS_GetDriver(self.cogr_ds)
--                if cogr_driver == NULL:
--                    raise ValueError("Null driver")
--
--                if isinstance(collection.name, string_types):
--                    name_b = collection.name.encode()
--                    name_c = name_b
--                    self.cogr_layer = ograpi.OGR_DS_GetLayerByName(
--                                        self.cogr_ds, name_c)
--                elif isinstance(collection.name, int):
--                    self.cogr_layer = ograpi.OGR_DS_GetLayer(
--                                        self.cogr_ds, collection.name)
--
--                if self.cogr_layer == NULL:
--                    raise RuntimeError(
--                        "Failed to get layer %s" % collection.name)
--            else:
--                raise OSError("No such file or directory %s" % path)
--
--            userencoding = self.collection.encoding
--            self._fileencoding = (userencoding or (
--                ograpi.OGR_L_TestCapability(self.cogr_layer, OLC_STRINGSASUTF8) and
--                OGR_DETECTED_ENCODING) or (
--                self.get_driver() == "ESRI Shapefile" and
--                'ISO-8859-1') or locale.getpreferredencoding()).upper()
--
--        elif collection.mode == 'w':
--            try:
--                path_b = path.encode('utf-8')
--            except UnicodeError:
--                path_b = path
--            path_c = path_b
--            driver_b = collection.driver.encode()
--            driver_c = driver_b
--
--            cogr_driver = ograpi.OGRGetDriverByName(driver_c)
--            if cogr_driver == NULL:
--                raise ValueError("Null driver")
--
--            if not os.path.exists(path):
--                cogr_ds = ograpi.OGR_Dr_CreateDataSource(
--                    cogr_driver, path_c, NULL)
--
--            else:
--                with cpl_errs:
--                    cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
--                if cogr_ds == NULL:
--                    cogr_ds = ograpi.OGR_Dr_CreateDataSource(
--                        cogr_driver, path_c, NULL)
--
--                elif collection.name is None:
--                    ograpi.OGR_DS_Destroy(cogr_ds)
--                    cogr_ds == NULL
--                    log.debug("Deleted pre-existing data at %s", path)
--                    
--                    cogr_ds = ograpi.OGR_Dr_CreateDataSource(
--                        cogr_driver, path_c, NULL)
--
--                else:
--                    pass
--
--            if cogr_ds == NULL:
--                raise RuntimeError("Failed to open %s" % path)
--            else:
--                self.cogr_ds = cogr_ds
--
--            # Set the spatial reference system from the crs given to the
--            # collection constructor. We by-pass the crs_wkt and crs
--            # properties because they aren't accessible until the layer
--            # is constructed (later).
--            col_crs = collection._crs_wkt or collection._crs
--            if col_crs:
--                cogr_srs = ograpi.OSRNewSpatialReference(NULL)
--                if cogr_srs == NULL:
--                    raise ValueError("NULL spatial reference")
--                # First, check for CRS strings like "EPSG:3857".
--                if isinstance(col_crs, string_types):
--                    proj_b = col_crs.encode('utf-8')
--                    proj_c = proj_b
--                    ograpi.OSRSetFromUserInput(cogr_srs, proj_c)
--                elif isinstance(col_crs, dict):
--                    # EPSG is a special case.
--                    init = col_crs.get('init')
--                    if init:
--                        log.debug("Init: %s", init)
--                        auth, val = init.split(':')
--                        if auth.upper() == 'EPSG':
--                            log.debug("Setting EPSG: %s", val)
--                            ograpi.OSRImportFromEPSG(cogr_srs, int(val))
--                    else:
--                        params = []
--                        col_crs['wktext'] = True
--                        for k, v in col_crs.items():
--                            if v is True or (k in ('no_defs', 'wktext') and v):
--                                params.append("+%s" % k)
--                            else:
--                                params.append("+%s=%s" % (k, v))
--                        proj = " ".join(params)
--                        log.debug("PROJ.4 to be imported: %r", proj)
--                        proj_b = proj.encode('utf-8')
--                        proj_c = proj_b
--                        ograpi.OSRImportFromProj4(cogr_srs, proj_c)
--                else:
--                    raise ValueError("Invalid CRS")
--
--                # Fixup, export to WKT, and set the GDAL dataset's projection.
--                ograpi.OSRFixup(cogr_srs)
--
--            # Figure out what encoding to use. The encoding parameter given
--            # to the collection constructor takes highest precedence, then
--            # 'iso-8859-1', then the system's default encoding as last resort.
--            sysencoding = locale.getpreferredencoding()
--            userencoding = collection.encoding
--            self._fileencoding = (userencoding or (
--                collection.driver == "ESRI Shapefile" and
--                'ISO-8859-1') or sysencoding).upper()
--
--            fileencoding = self.get_fileencoding()
--            if fileencoding:
--                fileencoding_b = fileencoding.encode()
--                fileencoding_c = fileencoding_b
--                options = ograpi.CSLSetNameValue(options, "ENCODING", fileencoding_c)
--
--            # Does the layer exist already? If so, we delete it.
--            layer_count = ograpi.OGR_DS_GetLayerCount(self.cogr_ds)
--            layer_names = []
--            for i in range(layer_count):
--                cogr_layer = ograpi.OGR_DS_GetLayer(cogr_ds, i)
--                name_c = ograpi.OGR_L_GetName(cogr_layer)
--                name_b = name_c
--                layer_names.append(name_b.decode('utf-8'))
--
--            idx = -1
--            if isinstance(collection.name, string_types):
--                if collection.name in layer_names:
--                    idx = layer_names.index(collection.name)
--            elif isinstance(collection.name, int):
--                if collection.name >= 0 and collection.name < layer_count:
--                    idx = collection.name
--            if idx >= 0:
--                log.debug("Deleted pre-existing layer at %s", collection.name)
--                ograpi.OGR_DS_DeleteLayer(self.cogr_ds, idx)
--            
--            # Create the named layer in the datasource.
--            name_b = collection.name.encode('utf-8')
--            name_c = name_b
--            self.cogr_layer = ograpi.OGR_DS_CreateLayer(
--                self.cogr_ds, 
--                name_c,
--                cogr_srs,
--                <unsigned int>[k for k,v in GEOMETRY_TYPES.items() if 
--                    v == collection.schema.get('geometry', 'Unknown')][0],
--                options
--                )
--
--            if cogr_srs != NULL:
--                ograpi.OSRDestroySpatialReference(cogr_srs)
--            if options != NULL:
--                ograpi.CSLDestroy(options)
--
--            if self.cogr_layer == NULL:
--                raise ValueError("Null layer")
--            log.debug("Created layer")
--            
--            # Next, make a layer definition from the given schema properties,
--            # which are an ordered dict since Fiona 1.0.1.
--            for key, value in collection.schema['properties'].items():
--                log.debug("Creating field: %s %s", key, value)
--
--                # Convert 'long' to 'int'. See
--                # https://github.com/Toblerity/Fiona/issues/101.
--                if value == 'long':
--                    value = 'int'
--                
--                # Is there a field width/precision?
--                width = precision = None
--                if ':' in value:
--                    value, fmt = value.split(':')
--                    if '.' in fmt:
--                        width, precision = map(int, fmt.split('.'))
--                    else:
--                        width = int(fmt)
--                
--                encoding = self.get_internalencoding()
--                key_bytes = key.encode(encoding)
--                cogr_fielddefn = ograpi.OGR_Fld_Create(
--                    key_bytes, 
--                    FIELD_TYPES.index(value) )
--                if cogr_fielddefn == NULL:
--                    raise ValueError("Null field definition")
--                if width:
--                    ograpi.OGR_Fld_SetWidth(cogr_fielddefn, width)
--                if precision:
--                    ograpi.OGR_Fld_SetPrecision(cogr_fielddefn, precision)
--                ograpi.OGR_L_CreateField(self.cogr_layer, cogr_fielddefn, 1)
--                ograpi.OGR_Fld_Destroy(cogr_fielddefn)
--            log.debug("Created fields")
--
--        # Mapping of the Python collection schema to the munged 
--        # OGR schema.
--        ogr_schema = self.get_schema()
--        self._schema_mapping = dict(zip(
--            collection.schema['properties'].keys(), 
--            ogr_schema['properties'].keys() ))
--
--        log.debug("Writing started")
--
--    def writerecs(self, records, collection):
--        """Writes buffered records to OGR."""
--        cdef void *cogr_driver
--        cdef void *cogr_feature
--
--        cdef void *cogr_layer = self.cogr_layer
--        if cogr_layer == NULL:
--            raise ValueError("Null layer")
--    
--        schema_geom_type = collection.schema['geometry']
--        cogr_driver = ograpi.OGR_DS_GetDriver(self.cogr_ds)
--        if ograpi.OGR_Dr_GetName(cogr_driver) == b"GeoJSON":
--            def validate_geometry_type(rec):
--                return True
--        elif ograpi.OGR_Dr_GetName(cogr_driver) == b"ESRI Shapefile" \
--                and "Point" not in collection.schema['geometry']:
--            schema_geom_type = collection.schema['geometry'].lstrip(
--                "3D ").lstrip("Multi")
--            def validate_geometry_type(rec):
--                return rec['geometry'] is None or \
--                rec['geometry']['type'].lstrip(
--                    "3D ").lstrip("Multi") == schema_geom_type
--        else:
--            schema_geom_type = collection.schema['geometry'].lstrip("3D ")
--            def validate_geometry_type(rec):
--                return rec['geometry'] is None or \
--                       rec['geometry']['type'].lstrip("3D ") == schema_geom_type
--
--        schema_props_keys = set(collection.schema['properties'].keys())
--        for record in records:
--            log.debug("Creating feature in layer: %s" % record)
--            # Validate against collection's schema.
--            if set(record['properties'].keys()) != schema_props_keys:
--                raise ValueError(
--                    "Record does not match collection schema: %r != %r" % (
--                        record['properties'].keys(), 
--                        list(schema_props_keys) ))
--            if not validate_geometry_type(record):
--                raise ValueError(
--                    "Record's geometry type does not match "
--                    "collection schema's geometry type: %r != %r" % (
--                         record['geometry']['type'],
--                         collection.schema['geometry'] ))
--
--            cogr_feature = OGRFeatureBuilder().build(record, collection)
--            result = ograpi.OGR_L_CreateFeature(cogr_layer, cogr_feature)
--            if result != OGRERR_NONE:
--                raise RuntimeError("Failed to write record: %s" % record)
--            _deleteOgrFeature(cogr_feature)
--
--    def sync(self, collection):
--        """Syncs OGR to disk."""
--        cdef void *cogr_ds = self.cogr_ds
--        cdef void *cogr_layer = self.cogr_layer
--        if cogr_ds == NULL:
--            raise ValueError("Null data source")
--        log.debug("Syncing OGR to disk")
--        retval = ograpi.OGR_DS_SyncToDisk(cogr_ds)
--        if retval != OGRERR_NONE:
--            raise RuntimeError("Failed to sync to disk")
--
--
--cdef class Iterator:
--
--    """Provides iterated access to feature data.
--    """
--
--    # Reference to its Collection
--    cdef collection
--    cdef encoding
--    cdef int next_index
--    cdef stop
--    cdef start
--    cdef step
--    cdef fastindex
--    cdef stepsign
--
--    def __init__(self, collection, 
--            start=None, stop=None, step=None, bbox=None, mask=None):
--        if collection.session is None:
--            raise ValueError("I/O operation on closed collection")
--        self.collection = collection
--        cdef Session session
--        cdef void *cogr_geometry
--        session = self.collection.session
--        cdef void *cogr_layer = session.cogr_layer
--        if cogr_layer == NULL:
--            raise ValueError("Null layer")
--        ograpi.OGR_L_ResetReading(cogr_layer)
--        
--        if bbox and mask:
--            raise ValueError("mask and bbox can not be set together")
--        
--        if bbox:
--            ograpi.OGR_L_SetSpatialFilterRect(
--                cogr_layer, bbox[0], bbox[1], bbox[2], bbox[3])
--        elif mask:
--            cogr_geometry = OGRGeomBuilder().build(mask)
--            ograpi.OGR_L_SetSpatialFilter(cogr_layer, cogr_geometry)
--            ograpi.OGR_G_DestroyGeometry(cogr_geometry)
--            
--        else:
--            ograpi.OGR_L_SetSpatialFilter(
--                cogr_layer, NULL)
--        self.encoding = session.get_internalencoding()
--
--        self.fastindex = ograpi.OGR_L_TestCapability(
--            session.cogr_layer, OLC_FASTSETNEXTBYINDEX)
--
--        ftcount = ograpi.OGR_L_GetFeatureCount(session.cogr_layer, 0)
--        if ftcount == -1 and ((start is not None and start < 0) or
--                              (stop is not None and stop < 0)):
--            raise IndexError(
--                "collection's dataset does not support negative slice indexes")
--
--        if stop is not None and stop < 0:
--            stop += ftcount
--
--        if start is None:
--            start = 0
--        if start is not None and start < 0:
--            start += ftcount
--
--        # step size
--        if step is None:
--            step = 1
--        if step == 0:
--            raise ValueError("slice step cannot be zero")
--        if step < 0 and not self.fastindex:
--            warnings.warn("Layer does not support" \
--                    "OLCFastSetNextByIndex, negative step size may" \
--                    " be slow", RuntimeWarning)
--        self.stepsign = int(math.copysign(1, step))
--        self.stop = stop
--        self.start = start
--        self.step = step
--
--        self.next_index = start
--        log.debug("Index: %d", self.next_index)
--        ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
--
--
--    def __iter__(self):
--        return self
--
--
--    def _next(self):
--        """Internal method to set read cursor to next item"""
--
--        cdef Session session
--        session = self.collection.session
--
--        # Check if next_index is valid
--        if self.next_index < 0:
--            raise StopIteration
--        
--        if self.stepsign == 1:
--            if self.next_index < self.start or (self.stop is not None and self.next_index >= self.stop):
--                raise StopIteration
--        else:
--            if self.next_index > self.start or (self.stop is not None and self.next_index <= self.stop):
--                raise StopIteration
--
--
--        # Set read cursor to next_item position
--        if self.step > 1 and self.fastindex:
--            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
--
--        elif self.step > 1 and not self.fastindex and not self.next_index == self.start:
--            for _ in range(self.step - 1):
--                # TODO rbuffat add test -> OGR_L_GetNextFeature increments cursor by 1, therefore self.step - 1 as one increment was performed when feature is read
--                cogr_feature = ograpi.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:
--            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
--
--        elif self.step == 0:
--            # ograpi.OGR_L_GetNextFeature increments read cursor by one
--            pass
--        elif self.step < 0:
--            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
--            
--        # set the next index
--        self.next_index += self.step
--
--
--    def __next__(self):
--        cdef void * cogr_feature
--        cdef Session session
--        session = self.collection.session
--
--        #Update read cursor
--        self._next()
--
--        # Get the next feature.
--        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
--        if cogr_feature == NULL:
--            raise StopIteration
--
--        feature = FeatureBuilder().build(
--            cogr_feature,
--            bbox=False,
--            encoding=self.encoding,
--            driver=self.collection.driver
--        )
--        _deleteOgrFeature(cogr_feature)
--        return feature
--
--
--cdef class ItemsIterator(Iterator):
--
--    def __next__(self):
--
--        cdef long fid
--        cdef void * cogr_feature
--        cdef Session session
--        session = self.collection.session
--
--        #Update read cursor
--        self._next()
--
--        # Get the next feature.
--        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
--        if cogr_feature == NULL:
--            raise StopIteration
--
--
--        fid = ograpi.OGR_F_GetFID(cogr_feature)
--        feature = FeatureBuilder().build(
--            cogr_feature,
--            bbox=False,
--            encoding=self.encoding,
--            driver=self.collection.driver
--        )
--        _deleteOgrFeature(cogr_feature)
--
--        return fid, feature
--
--
--cdef class KeysIterator(Iterator):
--
--    def __next__(self):
--        cdef long fid
--        cdef void * cogr_feature
--        cdef Session session
--        session = self.collection.session
--
--        #Update read cursor
--        self._next()
--
--        # Get the next feature.
--        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
--        if cogr_feature == NULL:
--            raise StopIteration
--
--        fid = ograpi.OGR_F_GetFID(cogr_feature)
--        _deleteOgrFeature(cogr_feature)
--
--        return fid
--
--
--def _listlayers(path):
--
--    """Provides a list of the layers in an OGR data source.
--    """
--    
--    cdef void *cogr_ds
--    cdef void *cogr_layer
--    cdef char *path_c
--    cdef char *name_c
--    
--    # Open OGR data source.
--    try:
--        path_b = path.encode('utf-8')
--    except UnicodeError:
--        path_b = path
--    path_c = path_b
--    with cpl_errs:
--        cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
--    if cogr_ds == NULL:
--        raise ValueError("No data available at path '%s'" % path)
--    
--    # Loop over the layers to get their names.
--    layer_count = ograpi.OGR_DS_GetLayerCount(cogr_ds)
--    layer_names = []
--    for i in range(layer_count):
--        cogr_layer = ograpi.OGR_DS_GetLayer(cogr_ds, i)
--        name_c = ograpi.OGR_L_GetName(cogr_layer)
--        name_b = name_c
--        layer_names.append(name_b.decode('utf-8'))
--    
--    # Close up data source.
--    if cogr_ds is not NULL:
--        ograpi.OGR_DS_Destroy(cogr_ds)
--    cogr_ds = NULL
--
--    return layer_names
--
--def buffer_to_virtual_file(bytesbuf):
--    """Maps a bytes buffer to a virtual file.
--    """
--    vsi_filename = os.path.join('/vsimem', uuid.uuid4().hex)
--    vsi_cfilename = vsi_filename if not isinstance(vsi_filename, string_types) else vsi_filename.encode('utf-8')
--
--    vsi_handle = ograpi.VSIFileFromMemBuffer(vsi_cfilename, bytesbuf, len(bytesbuf), 0)
--    if vsi_handle == NULL:
--        raise OSError('failed to map buffer to file')
--    if ograpi.VSIFCloseL(vsi_handle) != 0:
--        raise OSError('failed to close mapped file handle')
--
--    return vsi_filename
--
--def remove_virtual_file(vsi_filename):
--    vsi_cfilename = vsi_filename if not isinstance(vsi_filename, string_types) else vsi_filename.encode('utf-8')
--    return ograpi.VSIUnlink(vsi_cfilename)
--
--
---- /dev/null
-+++ b/fiona/ogrext1.pyx
-@@ -0,0 +1,1231 @@
-+# These are extension functions and classes using the OGR C API.
-+
-+import datetime
-+import json
-+import locale
-+import logging
-+import os
-+import sys
-+import warnings
-+import math
-+import uuid
-+
-+from six import integer_types, string_types, text_type
-+
-+from fiona cimport ograpi
-+from fiona._geometry cimport GeomBuilder, OGRGeomBuilder
-+from fiona._err import cpl_errs
-+from fiona._geometry import GEOMETRY_TYPES
-+from fiona.errors import DriverError, SchemaError, CRSError, FionaValueError
-+from fiona.odict import OrderedDict
-+from fiona.rfc3339 import parse_date, parse_datetime, parse_time
-+from fiona.rfc3339 import FionaDateType, FionaDateTimeType, FionaTimeType
-+
-+
-+log = logging.getLogger("Fiona")
-+class NullHandler(logging.Handler):
-+    def emit(self, record):
-+        pass
-+log.addHandler(NullHandler())
-+
-+
-+# Mapping of OGR integer field types to Fiona field type names.
-+#
-+# Lists are currently unsupported in this version, but might be done as
-+# arrays in a future version.
-+
-+FIELD_TYPES = [
-+    'int',          # OFTInteger, Simple 32bit integer
-+    None,           # OFTIntegerList, List of 32bit integers
-+    'float',        # OFTReal, Double Precision floating point
-+    None,           # OFTRealList, List of doubles
-+    'str',          # OFTString, String of ASCII chars
-+    None,           # OFTStringList, Array of strings
-+    None,           # OFTWideString, deprecated
-+    None,           # OFTWideStringList, deprecated
-+    None,           # OFTBinary, Raw Binary data
-+    'date',         # OFTDate, Date
-+    'time',         # OFTTime, Time
-+    'datetime',     # OFTDateTime, Date and Time
-+    'int',          # OFTInteger64, Single 64bit integer #Not supported
-+    None,           # OFTInteger64List, List of 64bit integers #Not supported
-+    ]
-+
-+# Mapping of Fiona field type names to Python types.
-+FIELD_TYPES_MAP = {
-+    'int':      int,
-+    'float':    float,
-+    'str':      text_type,
-+    'date':     FionaDateType,
-+    'time':     FionaTimeType,
-+    'datetime': FionaDateTimeType
-+   }
-+
-+# OGR Layer capability
-+OLC_RANDOMREAD = b"RandomRead"
-+OLC_SEQUENTIALWRITE = b"SequentialWrite"
-+OLC_RANDOMWRITE = b"RandomWrite"
-+OLC_FASTSPATIALFILTER = b"FastSpatialFilter"
-+OLC_FASTFEATURECOUNT = b"FastFeatureCount"
-+OLC_FASTGETEXTENT = b"FastGetExtent"
-+OLC_FASTSETNEXTBYINDEX = b"FastSetNextByIndex"
-+OLC_CREATEFIELD = b"CreateField"
-+OLC_CREATEGEOMFIELD = b"CreateGeomField"
-+OLC_DELETEFIELD = b"DeleteField"
-+OLC_REORDERFIELDS = b"ReorderFields"
-+OLC_ALTERFIELDDEFN = b"AlterFieldDefn"
-+OLC_DELETEFEATURE = b"DeleteFeature"
-+OLC_STRINGSASUTF8 = b"StringsAsUTF8"
-+OLC_TRANSACTIONS = b"Transactions"
-+
-+# OGR integer error types.
-+
-+OGRERR_NONE = 0
-+OGRERR_NOT_ENOUGH_DATA = 1    # not enough data to deserialize */
-+OGRERR_NOT_ENOUGH_MEMORY = 2
-+OGRERR_UNSUPPORTED_GEOMETRY_TYPE = 3
-+OGRERR_UNSUPPORTED_OPERATION = 4
-+OGRERR_CORRUPT_DATA = 5
-+OGRERR_FAILURE = 6
-+OGRERR_UNSUPPORTED_SRS = 7
-+OGRERR_INVALID_HANDLE = 8
-+
-+
-+def _explode(coords):
-+    """Explode a GeoJSON geometry's coordinates object and yield
-+    coordinate tuples. As long as the input is conforming, the type of
-+    the geometry doesn't matter."""
-+    for e in coords:
-+        if isinstance(e, (float, int)):
-+            yield coords
-+            break
-+        else:
-+            for f in _explode(e):
-+                yield f
-+
-+
-+def _bounds(geometry):
-+    """Bounding box of a GeoJSON geometry"""
-+    try:
-+        xyz = tuple(zip(*list(_explode(geometry['coordinates']))))
-+        return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1])
-+    except (KeyError, TypeError):
-+        return None
-+
-+def calc_gdal_version_num(maj, min, rev):
-+    """Calculates the internal gdal version number based on major, minor and revision"""
-+    return int(maj * 1000000 + min * 10000 + rev*100)
-+
-+def get_gdal_version_num():
-+    """Return current internal version number of gdal"""
-+    return int(ograpi.GDALVersionInfo("VERSION_NUM"))
-+
-+def get_gdal_release_name():
-+    """Return release name of gdal"""
-+    return ograpi.GDALVersionInfo("RELEASE_NAME")
-+
-+
-+# Feature extension classes and functions follow.
-+
-+cdef class FeatureBuilder:
-+    """Build Fiona features from OGR feature pointers.
-+
-+    No OGR objects are allocated by this function and the feature
-+    argument is not destroyed.
-+    """
-+
-+    cdef build(self, void *feature, encoding='utf-8', bbox=False, driver=None):
-+        # The only method anyone ever needs to call
-+        cdef void *fdefn
-+        cdef int i
-+        cdef int y = 0
-+        cdef int m = 0
-+        cdef int d = 0
-+        cdef int hh = 0
-+        cdef int mm = 0
-+        cdef int ss = 0
-+        cdef int tz = 0
-+        cdef int retval
-+        cdef char *key_c
-+        props = OrderedDict()
-+        for i in range(ograpi.OGR_F_GetFieldCount(feature)):
-+            fdefn = ograpi.OGR_F_GetFieldDefnRef(feature, i)
-+            if fdefn == NULL:
-+                raise ValueError("Null feature definition")
-+            key_c = ograpi.OGR_Fld_GetNameRef(fdefn)
-+            if key_c == NULL:
-+                raise ValueError("Null field name reference")
-+            key_b = key_c
-+            key = key_b.decode(encoding)
-+            fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(fdefn)]
-+            if not fieldtypename:
-+                log.warn(
-+                    "Skipping field %s: invalid type %s", 
-+                    key,
-+                    ograpi.OGR_Fld_GetType(fdefn))
-+                continue
-+
-+            # TODO: other types
-+            fieldtype = FIELD_TYPES_MAP[fieldtypename]
-+            if not ograpi.OGR_F_IsFieldSet(feature, i):
-+                props[key] = None
-+            elif fieldtype is int:
-+                props[key] = ograpi.OGR_F_GetFieldAsInteger(feature, i)
-+            elif fieldtype is float:
-+                props[key] = ograpi.OGR_F_GetFieldAsDouble(feature, i)
-+
-+            elif fieldtype is text_type:
-+                try:
-+                    val = ograpi.OGR_F_GetFieldAsString(feature, i)
-+                    val = val.decode(encoding)
-+                except UnicodeDecodeError:
-+                    log.warn(
-+                        "Failed to decode %s using %s codec", val, encoding)
-+
-+                # Does the text contain a JSON object? Let's check.
-+                # Let's check as cheaply as we can.
-+                if driver == 'GeoJSON' and val.startswith('{'):
-+                    try:
-+                        val = json.loads(val)
-+                    except ValueError as err:
-+                        log.warn(str(err))
-+
-+                # Now add to the properties object.
-+                props[key] = val
-+
-+            elif fieldtype in (FionaDateType, FionaTimeType, FionaDateTimeType):
-+                retval = ograpi.OGR_F_GetFieldAsDateTime(
-+                    feature, i, &y, &m, &d, &hh, &mm, &ss, &tz)
-+                if fieldtype is FionaDateType:
-+                    props[key] = datetime.date(y, m, d).isoformat()
-+                elif fieldtype is FionaTimeType:
-+                    props[key] = datetime.time(hh, mm, ss).isoformat()
-+                else:
-+                    props[key] = datetime.datetime(
-+                        y, m, d, hh, mm, ss).isoformat()
-+            else:
-+                log.debug("%s: None, fieldtype: %r, %r" % (key, fieldtype, fieldtype in string_types))
-+                props[key] = None
-+
-+        cdef void *cogr_geometry = ograpi.OGR_F_GetGeometryRef(feature)
-+        if cogr_geometry is not NULL:
-+            geom = GeomBuilder().build(cogr_geometry)
-+        else:
-+            geom = None
-+        return {
-+            'type': 'Feature',
-+            'id': str(ograpi.OGR_F_GetFID(feature)),
-+            'geometry': geom,
-+            'properties': props }
-+
-+
-+cdef class OGRFeatureBuilder:
-+    
-+    """Builds an OGR Feature from a Fiona feature mapping.
-+
-+    Allocates one OGR Feature which should be destroyed by the caller.
-+    Borrows a layer definition from the collection.
-+    """
-+    
-+    cdef void * build(self, feature, collection) except NULL:
-+        cdef void *cogr_geometry = NULL
-+        cdef char *string_c
-+        cdef WritingSession session
-+        session = collection.session
-+        cdef void *cogr_layer = session.cogr_layer
-+        if cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cdef void *cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(cogr_layer)
-+        if cogr_featuredefn == NULL:
-+            raise ValueError("Null feature definition")
-+        cdef void *cogr_feature = ograpi.OGR_F_Create(cogr_featuredefn)
-+        if cogr_feature == NULL:
-+            raise ValueError("Null feature")
-+        
-+        if feature['geometry'] is not None:
-+            cogr_geometry = OGRGeomBuilder().build(
-+                                feature['geometry'])
-+        ograpi.OGR_F_SetGeometryDirectly(cogr_feature, cogr_geometry)
-+        
-+        # OGR_F_SetFieldString takes UTF-8 encoded strings ('bytes' in 
-+        # Python 3).
-+        encoding = session.get_internalencoding()
-+
-+        for key, value in feature['properties'].items():
-+            log.debug(
-+                "Looking up %s in %s", key, repr(session._schema_mapping))
-+            ogr_key = session._schema_mapping[key]
-+            schema_type = collection.schema['properties'][key]
-+            try:
-+                key_bytes = ogr_key.encode(encoding)
-+            except UnicodeDecodeError:
-+                log.warn("Failed to encode %s using %s codec", key, encoding)
-+                key_bytes = ogr_key
-+            key_c = key_bytes
-+            i = ograpi.OGR_F_GetFieldIndex(cogr_feature, key_c)
-+            if i < 0:
-+                continue
-+
-+            # Special case: serialize dicts to assist OGR.
-+            if isinstance(value, dict):
-+                value = json.dumps(value)
-+
-+            # Continue over the standard OGR types.
-+            if isinstance(value, integer_types):
-+                ograpi.OGR_F_SetFieldInteger(cogr_feature, i, value)
-+            elif isinstance(value, float):
-+                ograpi.OGR_F_SetFieldDouble(cogr_feature, i, value)
-+            elif (isinstance(value, string_types) 
-+            and schema_type in ['date', 'time', 'datetime']):
-+                if schema_type == 'date':
-+                    y, m, d, hh, mm, ss, ff = parse_date(value)
-+                elif schema_type == 'time':
-+                    y, m, d, hh, mm, ss, ff = parse_time(value)
-+                else:
-+                    y, m, d, hh, mm, ss, ff = parse_datetime(value)
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, y, m, d, hh, mm, ss, 0)
-+            elif (isinstance(value, datetime.date)
-+            and schema_type == 'date'):
-+                y, m, d = value.year, value.month, value.day
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, y, m, d, 0, 0, 0, 0)
-+            elif (isinstance(value, datetime.datetime)
-+            and schema_type == 'datetime'):
-+                y, m, d = value.year, value.month, value.day
-+                hh, mm, ss = value.hour, value.minute, value.second
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, y, m, d, hh, mm, ss, 0)
-+            elif (isinstance(value, datetime.time)
-+            and schema_type == 'time'):
-+                hh, mm, ss = value.hour, value.minute, value.second
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, 0, 0, 0, hh, mm, ss, 0)
-+            elif isinstance(value, string_types):
-+                try:
-+                    value_bytes = value.encode(encoding)
-+                except UnicodeDecodeError:
-+                    log.warn(
-+                        "Failed to encode %s using %s codec", value, encoding)
-+                    value_bytes = value
-+                string_c = value_bytes
-+                ograpi.OGR_F_SetFieldString(cogr_feature, i, string_c)
-+            elif value is None:
-+                pass # keep field unset/null
-+            else:
-+                raise ValueError("Invalid field type %s" % type(value))
-+            log.debug("Set field %s: %s" % (key, value))
-+        return cogr_feature
-+
-+
-+cdef _deleteOgrFeature(void *cogr_feature):
-+    """Delete an OGR feature"""
-+    if cogr_feature is not NULL:
-+        ograpi.OGR_F_Destroy(cogr_feature)
-+    cogr_feature = NULL
-+
-+
-+def featureRT(feature, collection):
-+    # For testing purposes only, leaks the JSON data
-+    cdef void *cogr_feature = OGRFeatureBuilder().build(feature, collection)
-+    cdef void *cogr_geometry = ograpi.OGR_F_GetGeometryRef(cogr_feature)
-+    if cogr_geometry == NULL:
-+        raise ValueError("Null geometry")
-+    log.debug("Geometry: %s" % ograpi.OGR_G_ExportToJson(cogr_geometry))
-+    encoding = collection.encoding or 'utf-8'
-+    result = FeatureBuilder().build(
-+        cogr_feature,
-+        bbox=False,
-+        encoding=encoding,
-+        driver=collection.driver
-+    )
-+    _deleteOgrFeature(cogr_feature)
-+    return result
-+
-+
-+# Collection-related extension classes and functions
-+
-+cdef class Session:
-+    
-+    cdef void *cogr_ds
-+    cdef void *cogr_layer
-+    cdef object _fileencoding
-+    cdef object _encoding
-+    cdef object collection
-+
-+    def __cinit__(self):
-+        self.cogr_ds = NULL
-+        self.cogr_layer = NULL
-+        self._fileencoding = None
-+        self._encoding = None
-+
-+    def __dealloc__(self):
-+        self.stop()
-+
-+    def start(self, collection):
-+        cdef const char *path_c = NULL
-+        cdef const char *name_c = NULL
-+        cdef void *drv = NULL
-+        cdef void *ds = NULL
-+
-+        if collection.path == '-':
-+            path = '/vsistdin/'
-+        else:
-+            path = collection.path
-+        try:
-+            path_b = path.encode('utf-8')
-+        except UnicodeDecodeError:
-+            # Presume already a UTF-8 encoded string
-+            path_b = path
-+        path_c = path_b
-+        
-+        with cpl_errs:
-+            drivers = []
-+            if collection._driver:
-+                drivers = [collection._driver]
-+            elif collection.enabled_drivers:
-+                drivers = collection.enabled_drivers
-+            if drivers:
-+                for name in drivers:
-+                    name_b = name.encode()
-+                    name_c = name_b
-+                    log.debug("Trying driver: %s", name)
-+                    drv = ograpi.OGRGetDriverByName(name_c)
-+                    if drv != NULL:
-+                        ds = ograpi.OGR_Dr_Open(drv, path_c, 0)
-+                    if ds != NULL:
-+                        self.cogr_ds = ds
-+                        collection._driver = name
-+                        break
-+            else:
-+                self.cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
-+
-+        if self.cogr_ds == NULL:
-+            raise FionaValueError(
-+                "No dataset found at path '%s' using drivers: %s" % (
-+                    collection.path,
-+                    drivers or '*'))
-+        
-+        if isinstance(collection.name, string_types):
-+            name_b = collection.name.encode('utf-8')
-+            name_c = name_b
-+            self.cogr_layer = ograpi.OGR_DS_GetLayerByName(
-+                                self.cogr_ds, name_c)
-+        elif isinstance(collection.name, int):
-+            self.cogr_layer = ograpi.OGR_DS_GetLayer(
-+                                self.cogr_ds, collection.name)
-+            name_c = ograpi.OGR_L_GetName(self.cogr_layer)
-+            name_b = name_c
-+            collection.name = name_b.decode('utf-8')
-+
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer: " + repr(collection.name))
-+        
-+        self.collection = collection
-+        
-+        userencoding = self.collection.encoding
-+        if userencoding:
-+            ograpi.CPLSetThreadLocalConfigOption('SHAPE_ENCODING', '')
-+            self._fileencoding = userencoding.upper()
-+        else:
-+            self._fileencoding = (
-+                ograpi.OGR_L_TestCapability(
-+                    self.cogr_layer, OLC_STRINGSASUTF8) and
-+                'utf-8') or (
-+                self.get_driver() == "ESRI Shapefile" and
-+                'ISO-8859-1') or locale.getpreferredencoding().upper()
-+
-+    def stop(self):
-+        self.cogr_layer = NULL
-+        if self.cogr_ds is not NULL:
-+            ograpi.OGR_DS_Destroy(self.cogr_ds)
-+        self.cogr_ds = NULL
-+
-+    def get_fileencoding(self):
-+        return self._fileencoding
-+
-+    def get_internalencoding(self):
-+        if not self._encoding:
-+            fileencoding = self.get_fileencoding()
-+            self._encoding = (
-+                ograpi.OGR_L_TestCapability(
-+                    self.cogr_layer, OLC_STRINGSASUTF8) and
-+                'utf-8') or fileencoding
-+        return self._encoding
-+
-+    def get_length(self):
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        return ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
-+
-+    def get_driver(self):
-+        cdef void *cogr_driver = ograpi.OGR_DS_GetDriver(self.cogr_ds)
-+        if cogr_driver == NULL:
-+            raise ValueError("Null driver")
-+        cdef char *name = ograpi.OGR_Dr_GetName(cogr_driver)
-+        driver_name = name
-+        return driver_name.decode()
-+ 
-+    def get_schema(self):
-+        cdef int i
-+        cdef int n
-+        cdef void *cogr_featuredefn
-+        cdef void *cogr_fielddefn
-+        cdef char *key_c
-+        props = []
-+        
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+
-+        cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(self.cogr_layer)
-+        if cogr_featuredefn == NULL:
-+            raise ValueError("Null feature definition")
-+        n = ograpi.OGR_FD_GetFieldCount(cogr_featuredefn)
-+        for i from 0 <= i < n:
-+            cogr_fielddefn = ograpi.OGR_FD_GetFieldDefn(cogr_featuredefn, i)
-+            if cogr_fielddefn == NULL:
-+                raise ValueError("Null field definition")
-+            key_c = ograpi.OGR_Fld_GetNameRef(cogr_fielddefn)
-+            key_b = key_c
-+            if not bool(key_b):
-+                raise ValueError("Invalid field name ref: %s" % key)
-+            key = key_b.decode(self.get_internalencoding())
-+            fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(cogr_fielddefn)]
-+            if not fieldtypename:
-+                log.warn(
-+                    "Skipping field %s: invalid type %s", 
-+                    key,
-+                    ograpi.OGR_Fld_GetType(cogr_fielddefn))
-+                continue
-+            val = fieldtypename
-+            if fieldtypename == 'float':
-+                fmt = ""
-+                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
-+                if width: # and width != 24:
-+                    fmt = ":%d" % width
-+                precision = ograpi.OGR_Fld_GetPrecision(cogr_fielddefn)
-+                if precision: # and precision != 15:
-+                    fmt += ".%d" % precision
-+                val = "float" + fmt
-+            elif fieldtypename == 'int':
-+                fmt = ""
-+                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
-+                if width: # and width != 11:
-+                    fmt = ":%d" % width
-+                val = fieldtypename + fmt
-+            elif fieldtypename == 'str':
-+                fmt = ""
-+                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
-+                if width: # and width != 80:
-+                    fmt = ":%d" % width
-+                val = fieldtypename + fmt
-+
-+            props.append((key, val))
-+
-+        cdef unsigned int geom_type = ograpi.OGR_FD_GetGeomType(
-+            cogr_featuredefn)
-+        return {
-+            'properties': OrderedDict(props), 
-+            'geometry': GEOMETRY_TYPES[geom_type]}
-+
-+    def get_crs(self):
-+        cdef char *proj_c = NULL
-+        cdef char *auth_key = NULL
-+        cdef char *auth_val = NULL
-+        cdef void *cogr_crs = NULL
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
-+        crs = {}
-+        if cogr_crs is not NULL:
-+            log.debug("Got coordinate system")
-+
-+            retval = ograpi.OSRAutoIdentifyEPSG(cogr_crs)
-+            if retval > 0:
-+                log.info("Failed to auto identify EPSG: %d", retval)
-+            
-+            auth_key = ograpi.OSRGetAuthorityName(cogr_crs, NULL)
-+            auth_val = ograpi.OSRGetAuthorityCode(cogr_crs, NULL)
-+
-+            if auth_key != NULL and auth_val != NULL:
-+                key_b = auth_key
-+                key = key_b.decode('utf-8')
-+                if key == 'EPSG':
-+                    val_b = auth_val
-+                    val = val_b.decode('utf-8')
-+                    crs['init'] = "epsg:" + val
-+            else:
-+                ograpi.OSRExportToProj4(cogr_crs, &proj_c)
-+                if proj_c == NULL:
-+                    raise ValueError("Null projection")
-+                proj_b = proj_c
-+                log.debug("Params: %s", proj_b)
-+                value = proj_b.decode()
-+                value = value.strip()
-+                for param in value.split():
-+                    kv = param.split("=")
-+                    if len(kv) == 2:
-+                        k, v = kv
-+                        try:
-+                            v = float(v)
-+                            if v % 1 == 0:
-+                                v = int(v)
-+                        except ValueError:
-+                            # Leave v as a string
-+                            pass
-+                    elif len(kv) == 1:
-+                        k, v = kv[0], True
-+                    else:
-+                        raise ValueError("Unexpected proj parameter %s" % param)
-+                    k = k.lstrip("+")
-+                    crs[k] = v
-+
-+            ograpi.CPLFree(proj_c)
-+        else:
-+            log.debug("Projection not found (cogr_crs was NULL)")
-+        return crs
-+
-+    def get_crs_wkt(self):
-+        cdef char *proj_c = NULL
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
-+        crs_wkt = ""
-+        if cogr_crs is not NULL:
-+            log.debug("Got coordinate system")
-+            ograpi.OSRExportToWkt(cogr_crs, &proj_c)
-+            if proj_c == NULL:
-+                raise ValueError("Null projection")
-+            proj_b = proj_c
-+            crs_wkt = proj_b.decode('utf-8')
-+            ograpi.CPLFree(proj_c)
-+        else:
-+            log.debug("Projection not found (cogr_crs was NULL)")
-+        return crs_wkt
-+
-+    def get_extent(self):
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cdef ograpi.OGREnvelope extent
-+        result = ograpi.OGR_L_GetExtent(self.cogr_layer, &extent, 1)
-+        return (extent.MinX, extent.MinY, extent.MaxX, extent.MaxY)
-+
-+    def has_feature(self, fid):
-+        """Provides access to feature data by FID.
-+
-+        Supports Collection.__contains__().
-+        """
-+        cdef void * cogr_feature
-+        fid = int(fid)
-+        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
-+        if cogr_feature != NULL:
-+            _deleteOgrFeature(cogr_feature)
-+            return True
-+        else:
-+            return False
-+
-+    def get_feature(self, fid):
-+        """Provides access to feature data by FID.
-+
-+        Supports Collection.__contains__().
-+        """
-+        cdef void * cogr_feature
-+        fid = int(fid)
-+        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
-+        if cogr_feature != NULL:
-+            _deleteOgrFeature(cogr_feature)
-+            return True
-+        else:
-+            return False
-+
-+
-+    def __getitem__(self, item):
-+        cdef void * cogr_feature
-+        if isinstance(item, slice):
-+            itr = Iterator(self.collection, item.start, item.stop, item.step)
-+            log.debug("Slice: %r", item)
-+            return list(itr)
-+        elif isinstance(item, int):
-+            index = item
-+            # from the back
-+            if index < 0:
-+                ftcount = ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
-+                if ftcount == -1:
-+                    raise IndexError(
-+                        "collection's dataset does not support negative indexes")
-+                index += ftcount
-+            cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, index)
-+            if cogr_feature == NULL:
-+                return None
-+            feature = FeatureBuilder().build(
-+                cogr_feature,
-+                bbox=False,
-+                encoding=self.get_internalencoding(),
-+                driver=self.collection.driver
-+            )
-+            _deleteOgrFeature(cogr_feature)
-+            return feature
-+
-+
-+    def isactive(self):
-+        if self.cogr_layer != NULL and self.cogr_ds != NULL:
-+            return 1
-+        else:
-+            return 0
-+
-+
-+cdef class WritingSession(Session):
-+    
-+    cdef object _schema_mapping
-+
-+    def start(self, collection):
-+        cdef void *cogr_fielddefn
-+        cdef void *cogr_driver
-+        cdef void *cogr_ds
-+        cdef void *cogr_layer
-+        cdef void *cogr_srs = NULL
-+        cdef char **options = NULL
-+        self.collection = collection
-+        cdef char *path_c
-+        cdef char *driver_c
-+        cdef char *name_c
-+        cdef char *proj_c
-+        cdef char *fileencoding_c
-+        path = collection.path
-+
-+        if collection.mode == 'a':
-+            if os.path.exists(path):
-+                try:
-+                    path_b = path.encode('utf-8')
-+                except UnicodeDecodeError:
-+                    path_b = path
-+                path_c = path_b
-+                with cpl_errs:
-+                    self.cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
-+                if self.cogr_ds == NULL:
-+                    raise RuntimeError("Failed to open %s" % path)
-+                cogr_driver = ograpi.OGR_DS_GetDriver(self.cogr_ds)
-+                if cogr_driver == NULL:
-+                    raise ValueError("Null driver")
-+
-+                if isinstance(collection.name, string_types):
-+                    name_b = collection.name.encode()
-+                    name_c = name_b
-+                    self.cogr_layer = ograpi.OGR_DS_GetLayerByName(
-+                                        self.cogr_ds, name_c)
-+                elif isinstance(collection.name, int):
-+                    self.cogr_layer = ograpi.OGR_DS_GetLayer(
-+                                        self.cogr_ds, collection.name)
-+
-+                if self.cogr_layer == NULL:
-+                    raise RuntimeError(
-+                        "Failed to get layer %s" % collection.name)
-+            else:
-+                raise OSError("No such file or directory %s" % path)
-+
-+            userencoding = self.collection.encoding
-+            self._fileencoding = (userencoding or (
-+                ograpi.OGR_L_TestCapability(self.cogr_layer, OLC_STRINGSASUTF8) and
-+                'utf-8') or (
-+                self.get_driver() == "ESRI Shapefile" and
-+                'ISO-8859-1') or locale.getpreferredencoding()).upper()
-+
-+        elif collection.mode == 'w':
-+            try:
-+                path_b = path.encode('utf-8')
-+            except UnicodeDecodeError:
-+                path_b = path
-+            path_c = path_b
-+            driver_b = collection.driver.encode()
-+            driver_c = driver_b
-+
-+            cogr_driver = ograpi.OGRGetDriverByName(driver_c)
-+            if cogr_driver == NULL:
-+                raise ValueError("Null driver")
-+
-+            if not os.path.exists(path):
-+                cogr_ds = ograpi.OGR_Dr_CreateDataSource(
-+                    cogr_driver, path_c, NULL)
-+
-+            else:
-+                with cpl_errs:
-+                    cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
-+                if cogr_ds == NULL:
-+                    cogr_ds = ograpi.OGR_Dr_CreateDataSource(
-+                        cogr_driver, path_c, NULL)
-+
-+                elif collection.name is None:
-+                    ograpi.OGR_DS_Destroy(cogr_ds)
-+                    cogr_ds == NULL
-+                    log.debug("Deleted pre-existing data at %s", path)
-+                    
-+                    cogr_ds = ograpi.OGR_Dr_CreateDataSource(
-+                        cogr_driver, path_c, NULL)
-+
-+                else:
-+                    pass
-+
-+            if cogr_ds == NULL:
-+                raise RuntimeError("Failed to open %s" % path)
-+            else:
-+                self.cogr_ds = cogr_ds
-+
-+            # Set the spatial reference system from the crs given to the
-+            # collection constructor. We by-pass the crs_wkt and crs
-+            # properties because they aren't accessible until the layer
-+            # is constructed (later).
-+            col_crs = collection._crs_wkt or collection._crs
-+            if col_crs:
-+                cogr_srs = ograpi.OSRNewSpatialReference(NULL)
-+                if cogr_srs == NULL:
-+                    raise ValueError("NULL spatial reference")
-+                # First, check for CRS strings like "EPSG:3857".
-+                if isinstance(col_crs, string_types):
-+                    proj_b = col_crs.encode('utf-8')
-+                    proj_c = proj_b
-+                    ograpi.OSRSetFromUserInput(cogr_srs, proj_c)
-+                elif isinstance(col_crs, dict):
-+                    # EPSG is a special case.
-+                    init = col_crs.get('init')
-+                    if init:
-+                        log.debug("Init: %s", init)
-+                        auth, val = init.split(':')
-+                        if auth.upper() == 'EPSG':
-+                            log.debug("Setting EPSG: %s", val)
-+                            ograpi.OSRImportFromEPSG(cogr_srs, int(val))
-+                    else:
-+                        params = []
-+                        col_crs['wktext'] = True
-+                        for k, v in col_crs.items():
-+                            if v is True or (k in ('no_defs', 'wktext') and v):
-+                                params.append("+%s" % k)
-+                            else:
-+                                params.append("+%s=%s" % (k, v))
-+                        proj = " ".join(params)
-+                        log.debug("PROJ.4 to be imported: %r", proj)
-+                        proj_b = proj.encode('utf-8')
-+                        proj_c = proj_b
-+                        ograpi.OSRImportFromProj4(cogr_srs, proj_c)
-+                else:
-+                    raise ValueError("Invalid CRS")
-+
-+                # Fixup, export to WKT, and set the GDAL dataset's projection.
-+                ograpi.OSRFixup(cogr_srs)
-+
-+            # Figure out what encoding to use. The encoding parameter given
-+            # to the collection constructor takes highest precedence, then
-+            # 'iso-8859-1', then the system's default encoding as last resort.
-+            sysencoding = locale.getpreferredencoding()
-+            userencoding = collection.encoding
-+            self._fileencoding = (userencoding or (
-+                collection.driver == "ESRI Shapefile" and
-+                'ISO-8859-1') or sysencoding).upper()
-+
-+            fileencoding = self.get_fileencoding()
-+            if fileencoding:
-+                fileencoding_b = fileencoding.encode()
-+                fileencoding_c = fileencoding_b
-+                options = ograpi.CSLSetNameValue(options, "ENCODING", fileencoding_c)
-+
-+            # Does the layer exist already? If so, we delete it.
-+            layer_count = ograpi.OGR_DS_GetLayerCount(self.cogr_ds)
-+            layer_names = []
-+            for i in range(layer_count):
-+                cogr_layer = ograpi.OGR_DS_GetLayer(cogr_ds, i)
-+                name_c = ograpi.OGR_L_GetName(cogr_layer)
-+                name_b = name_c
-+                layer_names.append(name_b.decode('utf-8'))
-+
-+            idx = -1
-+            if isinstance(collection.name, string_types):
-+                if collection.name in layer_names:
-+                    idx = layer_names.index(collection.name)
-+            elif isinstance(collection.name, int):
-+                if collection.name >= 0 and collection.name < layer_count:
-+                    idx = collection.name
-+            if idx >= 0:
-+                log.debug("Deleted pre-existing layer at %s", collection.name)
-+                ograpi.OGR_DS_DeleteLayer(self.cogr_ds, idx)
-+            
-+            # Create the named layer in the datasource.
-+            name_b = collection.name.encode('utf-8')
-+            name_c = name_b
-+            self.cogr_layer = ograpi.OGR_DS_CreateLayer(
-+                self.cogr_ds, 
-+                name_c,
-+                cogr_srs,
-+                <unsigned int>[k for k,v in GEOMETRY_TYPES.items() if 
-+                    v == collection.schema.get('geometry', 'Unknown')][0],
-+                options
-+                )
-+
-+            if cogr_srs != NULL:
-+                ograpi.OSRDestroySpatialReference(cogr_srs)
-+            if options != NULL:
-+                ograpi.CSLDestroy(options)
-+
-+            if self.cogr_layer == NULL:
-+                raise ValueError("Null layer")
-+            log.debug("Created layer")
-+            
-+            # Next, make a layer definition from the given schema properties,
-+            # which are an ordered dict since Fiona 1.0.1.
-+            for key, value in collection.schema['properties'].items():
-+                log.debug("Creating field: %s %s", key, value)
-+
-+                # Convert 'long' to 'int'. See
-+                # https://github.com/Toblerity/Fiona/issues/101.
-+                if value == 'long':
-+                    value = 'int'
-+                
-+                # Is there a field width/precision?
-+                width = precision = None
-+                if ':' in value:
-+                    value, fmt = value.split(':')
-+                    if '.' in fmt:
-+                        width, precision = map(int, fmt.split('.'))
-+                    else:
-+                        width = int(fmt)
-+                
-+                encoding = self.get_internalencoding()
-+                key_bytes = key.encode(encoding)
-+                cogr_fielddefn = ograpi.OGR_Fld_Create(
-+                    key_bytes, 
-+                    FIELD_TYPES.index(value) )
-+                if cogr_fielddefn == NULL:
-+                    raise ValueError("Null field definition")
-+                if width:
-+                    ograpi.OGR_Fld_SetWidth(cogr_fielddefn, width)
-+                if precision:
-+                    ograpi.OGR_Fld_SetPrecision(cogr_fielddefn, precision)
-+                ograpi.OGR_L_CreateField(self.cogr_layer, cogr_fielddefn, 1)
-+                ograpi.OGR_Fld_Destroy(cogr_fielddefn)
-+            log.debug("Created fields")
-+
-+        # Mapping of the Python collection schema to the munged 
-+        # OGR schema.
-+        ogr_schema = self.get_schema()
-+        self._schema_mapping = dict(zip(
-+            collection.schema['properties'].keys(), 
-+            ogr_schema['properties'].keys() ))
-+
-+        log.debug("Writing started")
-+
-+    def writerecs(self, records, collection):
-+        """Writes buffered records to OGR."""
-+        cdef void *cogr_driver
-+        cdef void *cogr_feature
-+
-+        cdef void *cogr_layer = self.cogr_layer
-+        if cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+    
-+        schema_geom_type = collection.schema['geometry']
-+        cogr_driver = ograpi.OGR_DS_GetDriver(self.cogr_ds)
-+        if ograpi.OGR_Dr_GetName(cogr_driver) == b"GeoJSON":
-+            def validate_geometry_type(rec):
-+                return True
-+        elif ograpi.OGR_Dr_GetName(cogr_driver) == b"ESRI Shapefile" \
-+                and "Point" not in collection.schema['geometry']:
-+            schema_geom_type = collection.schema['geometry'].lstrip(
-+                "3D ").lstrip("Multi")
-+            def validate_geometry_type(rec):
-+                return rec['geometry'] is None or \
-+                rec['geometry']['type'].lstrip(
-+                    "3D ").lstrip("Multi") == schema_geom_type
-+        else:
-+            schema_geom_type = collection.schema['geometry'].lstrip("3D ")
-+            def validate_geometry_type(rec):
-+                return rec['geometry'] is None or \
-+                       rec['geometry']['type'].lstrip("3D ") == schema_geom_type
-+
-+        schema_props_keys = set(collection.schema['properties'].keys())
-+        for record in records:
-+            log.debug("Creating feature in layer: %s" % record)
-+            # Validate against collection's schema.
-+            if set(record['properties'].keys()) != schema_props_keys:
-+                raise ValueError(
-+                    "Record does not match collection schema: %r != %r" % (
-+                        record['properties'].keys(), 
-+                        list(schema_props_keys) ))
-+            if not validate_geometry_type(record):
-+                raise ValueError(
-+                    "Record's geometry type does not match "
-+                    "collection schema's geometry type: %r != %r" % (
-+                         record['geometry']['type'],
-+                         collection.schema['geometry'] ))
-+
-+            cogr_feature = OGRFeatureBuilder().build(record, collection)
-+            result = ograpi.OGR_L_CreateFeature(cogr_layer, cogr_feature)
-+            if result != OGRERR_NONE:
-+                raise RuntimeError("Failed to write record: %s" % record)
-+            _deleteOgrFeature(cogr_feature)
-+
-+    def sync(self, collection):
-+        """Syncs OGR to disk."""
-+        cdef void *cogr_ds = self.cogr_ds
-+        cdef void *cogr_layer = self.cogr_layer
-+        if cogr_ds == NULL:
-+            raise ValueError("Null data source")
-+        log.debug("Syncing OGR to disk")
-+        retval = ograpi.OGR_DS_SyncToDisk(cogr_ds)
-+        if retval != OGRERR_NONE:
-+            raise RuntimeError("Failed to sync to disk")
-+
-+
-+cdef class Iterator:
-+
-+    """Provides iterated access to feature data.
-+    """
-+
-+    # Reference to its Collection
-+    cdef collection
-+    cdef encoding
-+    cdef int next_index
-+    cdef stop
-+    cdef start
-+    cdef step
-+    cdef fastindex
-+    cdef stepsign
-+
-+    def __init__(self, collection, 
-+            start=None, stop=None, step=None, bbox=None, mask=None):
-+        if collection.session is None:
-+            raise ValueError("I/O operation on closed collection")
-+        self.collection = collection
-+        cdef Session session
-+        cdef void *cogr_geometry
-+        session = self.collection.session
-+        cdef void *cogr_layer = session.cogr_layer
-+        if cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        ograpi.OGR_L_ResetReading(cogr_layer)
-+        
-+        if bbox and mask:
-+            raise ValueError("mask and bbox can not be set together")
-+        
-+        if bbox:
-+            ograpi.OGR_L_SetSpatialFilterRect(
-+                cogr_layer, bbox[0], bbox[1], bbox[2], bbox[3])
-+        elif mask:
-+            cogr_geometry = OGRGeomBuilder().build(mask)
-+            ograpi.OGR_L_SetSpatialFilter(cogr_layer, cogr_geometry)
-+            ograpi.OGR_G_DestroyGeometry(cogr_geometry)
-+            
-+        else:
-+            ograpi.OGR_L_SetSpatialFilter(
-+                cogr_layer, NULL)
-+        self.encoding = session.get_internalencoding()
-+
-+        self.fastindex = ograpi.OGR_L_TestCapability(
-+            session.cogr_layer, OLC_FASTSETNEXTBYINDEX)
-+
-+        ftcount = ograpi.OGR_L_GetFeatureCount(session.cogr_layer, 0)
-+        if ftcount == -1 and ((start is not None and start < 0) or
-+                              (stop is not None and stop < 0)):
-+            raise IndexError(
-+                "collection's dataset does not support negative slice indexes")
-+
-+        if stop is not None and stop < 0:
-+            stop += ftcount
-+
-+        if start is None:
-+            start = 0
-+        if start is not None and start < 0:
-+            start += ftcount
-+
-+        # step size
-+        if step is None:
-+            step = 1
-+        if step == 0:
-+            raise ValueError("slice step cannot be zero")
-+        if step < 0 and not self.fastindex:
-+            warnings.warn("Layer does not support" \
-+                    "OLCFastSetNextByIndex, negative step size may" \
-+                    " be slow", RuntimeWarning)
-+        self.stepsign = int(math.copysign(1, step))
-+        self.stop = stop
-+        self.start = start
-+        self.step = step
-+
-+        self.next_index = start
-+        log.debug("Index: %d", self.next_index)
-+        ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+
-+
-+    def __iter__(self):
-+        return self
-+
-+
-+    def _next(self):
-+        """Internal method to set read cursor to next item"""
-+
-+        cdef Session session
-+        session = self.collection.session
-+
-+        # Check if next_index is valid
-+        if self.next_index < 0:
-+            raise StopIteration
-+        
-+        if self.stepsign == 1:
-+            if self.next_index < self.start or (self.stop is not None and self.next_index >= self.stop):
-+                raise StopIteration
-+        else:
-+            if self.next_index > self.start or (self.stop is not None and self.next_index <= self.stop):
-+                raise StopIteration
-+
-+
-+        # Set read cursor to next_item position
-+        if self.step > 1 and self.fastindex:
-+            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+
-+        elif self.step > 1 and not self.fastindex and not self.next_index == self.start:
-+            for _ in range(self.step - 1):
-+                # TODO rbuffat add test -> OGR_L_GetNextFeature increments cursor by 1, therefore self.step - 1 as one increment was performed when feature is read
-+                cogr_feature = ograpi.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:
-+            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+
-+        elif self.step == 0:
-+            # ograpi.OGR_L_GetNextFeature increments read cursor by one
-+            pass
-+        elif self.step < 0:
-+            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+            
-+        # set the next index
-+        self.next_index += self.step
-+
-+
-+    def __next__(self):
-+        cdef void * cogr_feature
-+        cdef Session session
-+        session = self.collection.session
-+
-+        #Update read cursor
-+        self._next()
-+
-+        # Get the next feature.
-+        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
-+        if cogr_feature == NULL:
-+            raise StopIteration
-+
-+        feature = FeatureBuilder().build(
-+            cogr_feature,
-+            bbox=False,
-+            encoding=self.encoding,
-+            driver=self.collection.driver
-+        )
-+        _deleteOgrFeature(cogr_feature)
-+        return feature
-+
-+
-+cdef class ItemsIterator(Iterator):
-+
-+    def __next__(self):
-+
-+        cdef long fid
-+        cdef void * cogr_feature
-+        cdef Session session
-+        session = self.collection.session
-+
-+        #Update read cursor
-+        self._next()
-+
-+        # Get the next feature.
-+        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
-+        if cogr_feature == NULL:
-+            raise StopIteration
-+
-+
-+        fid = ograpi.OGR_F_GetFID(cogr_feature)
-+        feature = FeatureBuilder().build(
-+            cogr_feature,
-+            bbox=False,
-+            encoding=self.encoding,
-+            driver=self.collection.driver
-+        )
-+        _deleteOgrFeature(cogr_feature)
-+
-+        return fid, feature
-+
-+
-+cdef class KeysIterator(Iterator):
-+
-+    def __next__(self):
-+        cdef long fid
-+        cdef void * cogr_feature
-+        cdef Session session
-+        session = self.collection.session
-+
-+        #Update read cursor
-+        self._next()
-+
-+        # Get the next feature.
-+        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
-+        if cogr_feature == NULL:
-+            raise StopIteration
-+
-+        fid = ograpi.OGR_F_GetFID(cogr_feature)
-+        _deleteOgrFeature(cogr_feature)
-+
-+        return fid
-+
-+
-+def _listlayers(path):
-+
-+    """Provides a list of the layers in an OGR data source.
-+    """
-+    
-+    cdef void *cogr_ds
-+    cdef void *cogr_layer
-+    cdef char *path_c
-+    cdef char *name_c
-+    
-+    # Open OGR data source.
-+    try:
-+        path_b = path.encode('utf-8')
-+    except UnicodeDecodeError:
-+        path_b = path
-+    path_c = path_b
-+    with cpl_errs:
-+        cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
-+    if cogr_ds == NULL:
-+        raise ValueError("No data available at path '%s'" % path)
-+    
-+    # Loop over the layers to get their names.
-+    layer_count = ograpi.OGR_DS_GetLayerCount(cogr_ds)
-+    layer_names = []
-+    for i in range(layer_count):
-+        cogr_layer = ograpi.OGR_DS_GetLayer(cogr_ds, i)
-+        name_c = ograpi.OGR_L_GetName(cogr_layer)
-+        name_b = name_c
-+        layer_names.append(name_b.decode('utf-8'))
-+    
-+    # Close up data source.
-+    if cogr_ds is not NULL:
-+        ograpi.OGR_DS_Destroy(cogr_ds)
-+    cogr_ds = NULL
-+
-+    return layer_names
-+
-+def buffer_to_virtual_file(bytesbuf):
-+    """Maps a bytes buffer to a virtual file.
-+    """
-+    vsi_filename = os.path.join('/vsimem', uuid.uuid4().hex)
-+    vsi_cfilename = vsi_filename if not isinstance(vsi_filename, string_types) else vsi_filename.encode('utf-8')
-+
-+    vsi_handle = ograpi.VSIFileFromMemBuffer(vsi_cfilename, bytesbuf, len(bytesbuf), 0)
-+    if vsi_handle == NULL:
-+        raise OSError('failed to map buffer to file')
-+    if ograpi.VSIFCloseL(vsi_handle) != 0:
-+        raise OSError('failed to close mapped file handle')
-+
-+    return vsi_filename
-+
-+def remove_virtual_file(vsi_filename):
-+    vsi_cfilename = vsi_filename if not isinstance(vsi_filename, string_types) else vsi_filename.encode('utf-8')
-+    return ograpi.VSIUnlink(vsi_cfilename)
-+
-+
---- /dev/null
-+++ b/fiona/ogrext2.pyx
-@@ -0,0 +1,1312 @@
-+# These are extension functions and classes using the OGR C API.
-+
-+import datetime
-+import json
-+import locale
-+import logging
-+import os
-+import sys
-+import warnings
-+import math
-+import uuid
-+
-+if sys.version_info > (3,):
-+    from builtins import int
-+else:
-+    from __builtin__ import int
-+
-+from six import integer_types, string_types, text_type
-+
-+from fiona cimport ograpi
-+from fiona._geometry cimport GeomBuilder, OGRGeomBuilder
-+from fiona._err import cpl_errs
-+from fiona._geometry import GEOMETRY_TYPES
-+from fiona.errors import DriverError, SchemaError, CRSError, FionaValueError
-+from fiona.odict import OrderedDict
-+from fiona.rfc3339 import parse_date, parse_datetime, parse_time
-+from fiona.rfc3339 import FionaDateType, FionaDateTimeType, FionaTimeType
-+
-+from libc.stdlib cimport malloc, free
-+from libc.string cimport strcmp
-+
-+
-+log = logging.getLogger("Fiona")
-+class NullHandler(logging.Handler):
-+    def emit(self, record):
-+        pass
-+log.addHandler(NullHandler())
-+
-+
-+# Mapping of OGR integer field types to Fiona field type names.
-+#
-+# Lists are currently unsupported in this version, but might be done as
-+# arrays in a future version.
-+
-+FIELD_TYPES = [
-+    'int',          # OFTInteger, Simple 32bit integer
-+    None,           # OFTIntegerList, List of 32bit integers
-+    'float',        # OFTReal, Double Precision floating point
-+    None,           # OFTRealList, List of doubles
-+    'str',          # OFTString, String of ASCII chars
-+    None,           # OFTStringList, Array of strings
-+    None,           # OFTWideString, deprecated
-+    None,           # OFTWideStringList, deprecated
-+    None,           # OFTBinary, Raw Binary data
-+    'date',         # OFTDate, Date
-+    'time',         # OFTTime, Time
-+    'datetime',     # OFTDateTime, Date and Time
-+    'int',          # OFTInteger64, Single 64bit integer
-+    None,           # OFTInteger64List, List of 64bit integers
-+    ]
-+
-+# Mapping of Fiona field type names to Python types.
-+FIELD_TYPES_MAP = {
-+    'int':      int,
-+    'float':    float,
-+    'str':      text_type,
-+    'date':     FionaDateType,
-+    'time':     FionaTimeType,
-+    'datetime': FionaDateTimeType
-+   }
-+
-+# OGR Layer capability
-+OLC_RANDOMREAD = b"RandomRead"
-+OLC_SEQUENTIALWRITE = b"SequentialWrite"
-+OLC_RANDOMWRITE = b"RandomWrite"
-+OLC_FASTSPATIALFILTER = b"FastSpatialFilter"
-+OLC_FASTFEATURECOUNT = b"FastFeatureCount"
-+OLC_FASTGETEXTENT = b"FastGetExtent"
-+OLC_FASTSETNEXTBYINDEX = b"FastSetNextByIndex"
-+OLC_CREATEFIELD = b"CreateField"
-+OLC_CREATEGEOMFIELD = b"CreateGeomField"
-+OLC_DELETEFIELD = b"DeleteField"
-+OLC_REORDERFIELDS = b"ReorderFields"
-+OLC_ALTERFIELDDEFN = b"AlterFieldDefn"
-+OLC_DELETEFEATURE = b"DeleteFeature"
-+OLC_STRINGSASUTF8 = b"StringsAsUTF8"
-+OLC_TRANSACTIONS = b"Transactions"
-+
-+# OGR integer error types.
-+
-+OGRERR_NONE = 0
-+OGRERR_NOT_ENOUGH_DATA = 1    # not enough data to deserialize */
-+OGRERR_NOT_ENOUGH_MEMORY = 2
-+OGRERR_UNSUPPORTED_GEOMETRY_TYPE = 3
-+OGRERR_UNSUPPORTED_OPERATION = 4
-+OGRERR_CORRUPT_DATA = 5
-+OGRERR_FAILURE = 6
-+OGRERR_UNSUPPORTED_SRS = 7
-+OGRERR_INVALID_HANDLE = 8
-+
-+
-+cdef char ** string_list(list_str):
-+    """
-+    Function by Stackoverflow User falsetru
-+    https://stackoverflow.com/questions/17511309/fast-string-array-cython
-+    """
-+    cdef char* s
-+    cdef char **ret = <char **>malloc(len(list_str) * sizeof(char *))
-+    for i in range(len(list_str)):
-+        s = list_str[i]
-+        ret[i] = s
-+    ret[i + 1] = NULL
-+    return ret
-+
-+def _explode(coords):
-+    """Explode a GeoJSON geometry's coordinates object and yield
-+    coordinate tuples. As long as the input is conforming, the type of
-+    the geometry doesn't matter."""
-+    for e in coords:
-+        if isinstance(e, (float, int)):
-+            yield coords
-+            break
-+        else:
-+            for f in _explode(e):
-+                yield f
-+
-+
-+def _bounds(geometry):
-+    """Bounding box of a GeoJSON geometry"""
-+    try:
-+        xyz = tuple(zip(*list(_explode(geometry['coordinates']))))
-+        return min(xyz[0]), min(xyz[1]), max(xyz[0]), max(xyz[1])
-+    except (KeyError, TypeError):
-+        return None
-+
-+def calc_gdal_version_num(maj, min, rev):
-+    """Calculates the internal gdal version number based on major, minor and revision"""
-+    return int(maj * 1000000 + min * 10000 + rev*100)
-+
-+def get_gdal_version_num():
-+    """Return current internal version number of gdal"""
-+    return int(ograpi.GDALVersionInfo("VERSION_NUM"))
-+
-+def get_gdal_release_name():
-+    """Return release name of gdal"""
-+    return ograpi.GDALVersionInfo("RELEASE_NAME")
-+
-+
-+# Feature extension classes and functions follow.
-+
-+cdef class FeatureBuilder:
-+    """Build Fiona features from OGR feature pointers.
-+
-+    No OGR objects are allocated by this function and the feature
-+    argument is not destroyed.
-+    """
-+
-+    cdef build(self, void *feature, encoding='utf-8', bbox=False, driver=None):
-+        # The only method anyone ever needs to call
-+        cdef void *fdefn
-+        cdef int i
-+        cdef int y = 0
-+        cdef int m = 0
-+        cdef int d = 0
-+        cdef int hh = 0
-+        cdef int mm = 0
-+        cdef int ss = 0
-+        cdef int tz = 0
-+        cdef int retval
-+        cdef char *key_c
-+        props = OrderedDict()
-+        for i in range(ograpi.OGR_F_GetFieldCount(feature)):
-+            fdefn = ograpi.OGR_F_GetFieldDefnRef(feature, i)
-+            if fdefn == NULL:
-+                raise ValueError("Null feature definition")
-+            key_c = ograpi.OGR_Fld_GetNameRef(fdefn)
-+            if key_c == NULL:
-+                raise ValueError("Null field name reference")
-+            key_b = key_c
-+            key = key_b.decode(encoding)
-+            fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(fdefn)]
-+            if not fieldtypename:
-+                log.warn(
-+                    "Skipping field %s: invalid type %s", 
-+                    key,
-+                    ograpi.OGR_Fld_GetType(fdefn))
-+                continue
-+
-+            # TODO: other types
-+            fieldtype = FIELD_TYPES_MAP[fieldtypename]
-+            if not ograpi.OGR_F_IsFieldSet(feature, i):
-+                props[key] = None
-+            elif fieldtype is int:
-+                props[key] = ograpi.OGR_F_GetFieldAsInteger64(feature, i)
-+            elif fieldtype is float:
-+                props[key] = ograpi.OGR_F_GetFieldAsDouble(feature, i)
-+
-+            elif fieldtype is text_type:
-+                try:
-+                    val = ograpi.OGR_F_GetFieldAsString(feature, i)
-+                    val = val.decode(encoding)
-+                except UnicodeDecodeError:
-+                    log.warn(
-+                        "Failed to decode %s using %s codec", val, encoding)
-+
-+                # Does the text contain a JSON object? Let's check.
-+                # Let's check as cheaply as we can.
-+                if driver == 'GeoJSON' and val.startswith('{'):
-+                    try:
-+                        val = json.loads(val)
-+                    except ValueError as err:
-+                        log.warn(str(err))
-+
-+                # Now add to the properties object.
-+                props[key] = val
-+
-+            elif fieldtype in (FionaDateType, FionaTimeType, FionaDateTimeType):
-+                retval = ograpi.OGR_F_GetFieldAsDateTime(
-+                    feature, i, &y, &m, &d, &hh, &mm, &ss, &tz)
-+                if fieldtype is FionaDateType:
-+                    props[key] = datetime.date(y, m, d).isoformat()
-+                elif fieldtype is FionaTimeType:
-+                    props[key] = datetime.time(hh, mm, ss).isoformat()
-+                else:
-+                    props[key] = datetime.datetime(
-+                        y, m, d, hh, mm, ss).isoformat()
-+            else:
-+                log.debug("%s: None, fieldtype: %r, %r" % (key, fieldtype, fieldtype in string_types))
-+                props[key] = None
-+
-+        cdef void *cogr_geometry = ograpi.OGR_F_GetGeometryRef(feature)
-+        if cogr_geometry is not NULL:
-+            geom = GeomBuilder().build(cogr_geometry)
-+        else:
-+            geom = None
-+        return {
-+            'type': 'Feature',
-+            'id': str(ograpi.OGR_F_GetFID(feature)),
-+            'geometry': geom,
-+            'properties': props }
-+
-+
-+cdef class OGRFeatureBuilder:
-+    
-+    """Builds an OGR Feature from a Fiona feature mapping.
-+
-+    Allocates one OGR Feature which should be destroyed by the caller.
-+    Borrows a layer definition from the collection.
-+    """
-+    
-+    cdef void * build(self, feature, collection) except NULL:
-+        cdef void *cogr_geometry = NULL
-+        cdef char *string_c
-+        cdef WritingSession session
-+        session = collection.session
-+        cdef void *cogr_layer = session.cogr_layer
-+        if cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cdef void *cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(cogr_layer)
-+        if cogr_featuredefn == NULL:
-+            raise ValueError("Null feature definition")
-+        cdef void *cogr_feature = ograpi.OGR_F_Create(cogr_featuredefn)
-+        if cogr_feature == NULL:
-+            raise ValueError("Null feature")
-+        
-+        if feature['geometry'] is not None:
-+            cogr_geometry = OGRGeomBuilder().build(
-+                                feature['geometry'])
-+        ograpi.OGR_F_SetGeometryDirectly(cogr_feature, cogr_geometry)
-+        
-+        # OGR_F_SetFieldString takes UTF-8 encoded strings ('bytes' in 
-+        # Python 3).
-+        encoding = session.get_internalencoding()
-+
-+        for key, value in feature['properties'].items():
-+            log.debug(
-+                "Looking up %s in %s", key, repr(session._schema_mapping))
-+            ogr_key = session._schema_mapping[key]
-+            schema_type = collection.schema['properties'][key]
-+            try:
-+                key_bytes = ogr_key.encode(encoding)
-+            except UnicodeDecodeError:
-+                log.warn("Failed to encode %s using %s codec", key, encoding)
-+                key_bytes = ogr_key
-+            key_c = key_bytes
-+            i = ograpi.OGR_F_GetFieldIndex(cogr_feature, key_c)
-+            if i < 0:
-+                continue
-+
-+            # Special case: serialize dicts to assist OGR.
-+            if isinstance(value, dict):
-+                value = json.dumps(value)
-+
-+            # Continue over the standard OGR types.
-+            if isinstance(value, integer_types):
-+                ograpi.OGR_F_SetFieldInteger64(cogr_feature, i, value)
-+            elif isinstance(value, float):
-+                ograpi.OGR_F_SetFieldDouble(cogr_feature, i, value)
-+            elif (isinstance(value, string_types) 
-+            and schema_type in ['date', 'time', 'datetime']):
-+                if schema_type == 'date':
-+                    y, m, d, hh, mm, ss, ff = parse_date(value)
-+                elif schema_type == 'time':
-+                    y, m, d, hh, mm, ss, ff = parse_time(value)
-+                else:
-+                    y, m, d, hh, mm, ss, ff = parse_datetime(value)
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, y, m, d, hh, mm, ss, 0)
-+            elif (isinstance(value, datetime.date)
-+            and schema_type == 'date'):
-+                y, m, d = value.year, value.month, value.day
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, y, m, d, 0, 0, 0, 0)
-+            elif (isinstance(value, datetime.datetime)
-+            and schema_type == 'datetime'):
-+                y, m, d = value.year, value.month, value.day
-+                hh, mm, ss = value.hour, value.minute, value.second
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, y, m, d, hh, mm, ss, 0)
-+            elif (isinstance(value, datetime.time)
-+            and schema_type == 'time'):
-+                hh, mm, ss = value.hour, value.minute, value.second
-+                ograpi.OGR_F_SetFieldDateTime(
-+                    cogr_feature, i, 0, 0, 0, hh, mm, ss, 0)
-+            elif isinstance(value, string_types):
-+                try:
-+                    value_bytes = value.encode(encoding)
-+                except UnicodeDecodeError:
-+                    log.warn(
-+                        "Failed to encode %s using %s codec", value, encoding)
-+                    value_bytes = value
-+                string_c = value_bytes
-+                ograpi.OGR_F_SetFieldString(cogr_feature, i, string_c)
-+            elif value is None:
-+                pass # keep field unset/null
-+            else:
-+                raise ValueError("Invalid field type %s" % type(value))
-+            log.debug("Set field %s: %s" % (key, value))
-+        return cogr_feature
-+
-+
-+cdef _deleteOgrFeature(void *cogr_feature):
-+    """Delete an OGR feature"""
-+    if cogr_feature is not NULL:
-+        ograpi.OGR_F_Destroy(cogr_feature)
-+    cogr_feature = NULL
-+
-+
-+def featureRT(feature, collection):
-+    # For testing purposes only, leaks the JSON data
-+    cdef void *cogr_feature = OGRFeatureBuilder().build(feature, collection)
-+    cdef void *cogr_geometry = ograpi.OGR_F_GetGeometryRef(cogr_feature)
-+    if cogr_geometry == NULL:
-+        raise ValueError("Null geometry")
-+    log.debug("Geometry: %s" % ograpi.OGR_G_ExportToJson(cogr_geometry))
-+    encoding = collection.encoding or 'utf-8'
-+    result = FeatureBuilder().build(
-+        cogr_feature,
-+        bbox=False,
-+        encoding=encoding,
-+        driver=collection.driver
-+    )
-+    _deleteOgrFeature(cogr_feature)
-+    return result
-+
-+
-+# Collection-related extension classes and functions
-+
-+cdef class Session:
-+    
-+    cdef void *cogr_ds
-+    cdef void *cogr_layer
-+    cdef object _fileencoding
-+    cdef object _encoding
-+    cdef object collection
-+
-+    def __cinit__(self):
-+        self.cogr_ds = NULL
-+        self.cogr_layer = NULL
-+        self._fileencoding = None
-+        self._encoding = None
-+
-+    def __dealloc__(self):
-+        self.stop()
-+
-+    def start(self, collection):
-+        cdef const char *path_c = NULL
-+        cdef const char *name_c = NULL
-+        cdef void *drv = NULL
-+        cdef void *ds = NULL
-+        cdef char ** drvs = NULL
-+        if collection.path == '-':
-+            path = '/vsistdin/'
-+        else:
-+            path = collection.path
-+        try:
-+            path_b = path.encode('utf-8')
-+        except UnicodeDecodeError:
-+            # Presume already a UTF-8 encoded string
-+            path_b = path
-+        path_c = path_b
-+        
-+        with cpl_errs:
-+            drivers = []
-+            if collection._driver:
-+                drivers = [collection._driver]
-+            elif collection.enabled_drivers:
-+                drivers = collection.enabled_drivers
-+            if drivers:
-+                for name in drivers:
-+                    name_b = name.encode()
-+                    name_c = name_b
-+                    log.debug("Trying driver: %s", name)
-+                    drv = ograpi.GDALGetDriverByName(name_c)
-+                    if drv != NULL:
-+                        drvs = string_list([name_b])
-+
-+                        flags = ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_READONLY
-+                        log.debug("GDALOpenEx({}, {}, {})".format(path_c, flags, [name_b]))
-+                        ds = ograpi.GDALOpenEx(path_c,
-+                                               flags,
-+                                               drvs,
-+                                               NULL,
-+                                               NULL)
-+                    if ds != NULL:
-+                        self.cogr_ds = ds
-+                        collection._driver = name
-+                        _driver = ograpi.GDALGetDatasetDriver(ds)
-+                        drv_name = ograpi.GDALGetDriverShortName(_driver)
-+                        log.debug("Driver: {} Success".format(drv_name))
-+
-+                        break
-+            else:
-+                self.cogr_ds = ograpi.GDALOpenEx(path_c,
-+                                                 ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_READONLY,
-+                                                 NULL,
-+                                                 NULL,
-+                                                 NULL)
-+
-+        if self.cogr_ds == NULL:
-+            raise FionaValueError(
-+                "No dataset found at path '%s' using drivers: %s" % (
-+                    collection.path,
-+                    drivers or '*'))
-+        
-+        if isinstance(collection.name, string_types):
-+            name_b = collection.name.encode('utf-8')
-+            name_c = name_b
-+            self.cogr_layer = ograpi.GDALDatasetGetLayerByName(
-+                                self.cogr_ds, name_c)
-+        elif isinstance(collection.name, int):
-+            self.cogr_layer = ograpi.GDALDatasetGetLayer(
-+                                self.cogr_ds, collection.name)
-+            name_c = ograpi.OGR_L_GetName(self.cogr_layer)
-+            name_b = name_c
-+            collection.name = name_b.decode('utf-8')
-+
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer: " + repr(collection.name))
-+        
-+        self.collection = collection
-+        
-+        userencoding = self.collection.encoding
-+        if userencoding:
-+            ograpi.CPLSetThreadLocalConfigOption('SHAPE_ENCODING', '')
-+            self._fileencoding = userencoding.upper()
-+        else:
-+            self._fileencoding = (
-+                ograpi.OGR_L_TestCapability(
-+                    self.cogr_layer, OLC_STRINGSASUTF8) and
-+                'utf-8') or (
-+                self.get_driver() == "ESRI Shapefile" and
-+                'ISO-8859-1') or locale.getpreferredencoding().upper()
-+
-+    def stop(self):
-+        self.cogr_layer = NULL
-+        if self.cogr_ds is not NULL:
-+            ograpi.GDALClose(self.cogr_ds)
-+        self.cogr_ds = NULL
-+
-+    def get_fileencoding(self):
-+        return self._fileencoding
-+
-+    def get_internalencoding(self):
-+        if not self._encoding:
-+            fileencoding = self.get_fileencoding()
-+            self._encoding = (
-+                ograpi.OGR_L_TestCapability(
-+                    self.cogr_layer, OLC_STRINGSASUTF8) and
-+                'utf-8') or fileencoding
-+        return self._encoding
-+
-+    def get_length(self):
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        return ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
-+
-+    def get_driver(self):
-+        cdef void *cogr_driver = ograpi.GDALGetDatasetDriver(self.cogr_ds)
-+        if cogr_driver == NULL:
-+            raise ValueError("Null driver")
-+        cdef char *name = ograpi.OGR_Dr_GetName(cogr_driver)
-+        driver_name = name
-+        return driver_name.decode()
-+ 
-+    def get_schema(self):
-+        cdef int i
-+        cdef int n
-+        cdef void *cogr_featuredefn
-+        cdef void *cogr_fielddefn
-+        cdef char *key_c
-+        props = []
-+        
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+
-+        cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(self.cogr_layer)
-+        if cogr_featuredefn == NULL:
-+            raise ValueError("Null feature definition")
-+        n = ograpi.OGR_FD_GetFieldCount(cogr_featuredefn)
-+        for i from 0 <= i < n:
-+            cogr_fielddefn = ograpi.OGR_FD_GetFieldDefn(cogr_featuredefn, i)
-+            if cogr_fielddefn == NULL:
-+                raise ValueError("Null field definition")
-+            key_c = ograpi.OGR_Fld_GetNameRef(cogr_fielddefn)
-+            key_b = key_c
-+            if not bool(key_b):
-+                raise ValueError("Invalid field name ref: %s" % key)
-+            key = key_b.decode(self.get_internalencoding())
-+            fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(cogr_fielddefn)]
-+            if not fieldtypename:
-+                log.warn(
-+                    "Skipping field %s: invalid type %s", 
-+                    key,
-+                    ograpi.OGR_Fld_GetType(cogr_fielddefn))
-+                continue
-+            val = fieldtypename
-+            if fieldtypename == 'float':
-+                fmt = ""
-+                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
-+                if width: # and width != 24:
-+                    fmt = ":%d" % width
-+                precision = ograpi.OGR_Fld_GetPrecision(cogr_fielddefn)
-+                if precision: # and precision != 15:
-+                    fmt += ".%d" % precision
-+                val = "float" + fmt
-+            elif fieldtypename == 'int':
-+                fmt = ""
-+                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
-+                if width: # and width != 11:
-+                    fmt = ":%d" % width
-+                val = fieldtypename + fmt
-+            elif fieldtypename == 'str':
-+                fmt = ""
-+                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
-+                if width: # and width != 80:
-+                    fmt = ":%d" % width
-+                val = fieldtypename + fmt
-+
-+            props.append((key, val))
-+
-+        cdef unsigned int geom_type = ograpi.OGR_FD_GetGeomType(
-+            cogr_featuredefn)
-+        return {
-+            'properties': OrderedDict(props), 
-+            'geometry': GEOMETRY_TYPES[geom_type]}
-+
-+    def get_crs(self):
-+        cdef char *proj_c = NULL
-+        cdef char *auth_key = NULL
-+        cdef char *auth_val = NULL
-+        cdef void *cogr_crs = NULL
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
-+        crs = {}
-+        if cogr_crs is not NULL:
-+            log.debug("Got coordinate system")
-+
-+            retval = ograpi.OSRAutoIdentifyEPSG(cogr_crs)
-+            if retval > 0:
-+                log.info("Failed to auto identify EPSG: %d", retval)
-+            
-+            auth_key = ograpi.OSRGetAuthorityName(cogr_crs, NULL)
-+            auth_val = ograpi.OSRGetAuthorityCode(cogr_crs, NULL)
-+
-+            if auth_key != NULL and auth_val != NULL:
-+                key_b = auth_key
-+                key = key_b.decode('utf-8')
-+                if key == 'EPSG':
-+                    val_b = auth_val
-+                    val = val_b.decode('utf-8')
-+                    crs['init'] = "epsg:" + val
-+            else:
-+                ograpi.OSRExportToProj4(cogr_crs, &proj_c)
-+                if proj_c == NULL:
-+                    raise ValueError("Null projection")
-+                proj_b = proj_c
-+                log.debug("Params: %s", proj_b)
-+                value = proj_b.decode()
-+                value = value.strip()
-+                for param in value.split():
-+                    kv = param.split("=")
-+                    if len(kv) == 2:
-+                        k, v = kv
-+                        try:
-+                            v = float(v)
-+                            if v % 1 == 0:
-+                                v = int(v)
-+                        except ValueError:
-+                            # Leave v as a string
-+                            pass
-+                    elif len(kv) == 1:
-+                        k, v = kv[0], True
-+                    else:
-+                        raise ValueError("Unexpected proj parameter %s" % param)
-+                    k = k.lstrip("+")
-+                    crs[k] = v
-+
-+            ograpi.CPLFree(proj_c)
-+        else:
-+            log.debug("Projection not found (cogr_crs was NULL)")
-+        return crs
-+
-+    def get_crs_wkt(self):
-+        cdef char *proj_c = NULL
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
-+        crs_wkt = ""
-+        if cogr_crs is not NULL:
-+            log.debug("Got coordinate system")
-+            ograpi.OSRExportToWkt(cogr_crs, &proj_c)
-+            if proj_c == NULL:
-+                raise ValueError("Null projection")
-+            proj_b = proj_c
-+            crs_wkt = proj_b.decode('utf-8')
-+            ograpi.CPLFree(proj_c)
-+        else:
-+            log.debug("Projection not found (cogr_crs was NULL)")        
-+        return crs_wkt
-+
-+    def get_extent(self):
-+        if self.cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        cdef ograpi.OGREnvelope extent
-+        result = ograpi.OGR_L_GetExtent(self.cogr_layer, &extent, 1)
-+        return (extent.MinX, extent.MinY, extent.MaxX, extent.MaxY)
-+
-+    def has_feature(self, fid):
-+        """Provides access to feature data by FID.
-+
-+        Supports Collection.__contains__().
-+        """
-+        cdef void * cogr_feature
-+        fid = int(fid)
-+        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
-+        if cogr_feature != NULL:
-+            _deleteOgrFeature(cogr_feature)
-+            return True
-+        else:
-+            return False
-+
-+    def get_feature(self, fid):
-+        """Provides access to feature data by FID.
-+
-+        Supports Collection.__contains__().
-+        """
-+        cdef void * cogr_feature
-+        fid = int(fid)
-+        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
-+        if cogr_feature != NULL:
-+            _deleteOgrFeature(cogr_feature)
-+            return True
-+        else:
-+            return False
-+
-+
-+    def __getitem__(self, item):
-+        cdef void * cogr_feature
-+        if isinstance(item, slice):
-+            itr = Iterator(self.collection, item.start, item.stop, item.step)
-+            log.debug("Slice: %r", item)
-+            return list(itr)
-+        elif isinstance(item, int):
-+            index = item
-+            # from the back
-+            if index < 0:
-+                ftcount = ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
-+                if ftcount == -1:
-+                    raise IndexError(
-+                        "collection's dataset does not support negative indexes")
-+                index += ftcount
-+            cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, index)
-+            if cogr_feature == NULL:
-+                return None
-+            feature = FeatureBuilder().build(
-+                cogr_feature,
-+                bbox=False,
-+                encoding=self.get_internalencoding(),
-+                driver=self.collection.driver
-+            )
-+            _deleteOgrFeature(cogr_feature)
-+            return feature
-+
-+
-+    def isactive(self):
-+        if self.cogr_layer != NULL and self.cogr_ds != NULL:
-+            return 1
-+        else:
-+            return 0
-+
-+
-+cdef class WritingSession(Session):
-+    
-+    cdef object _schema_mapping
-+
-+    def start(self, collection):
-+        cdef void *cogr_fielddefn
-+        cdef void *cogr_driver
-+        cdef void *cogr_ds
-+        cdef void *cogr_layer
-+        cdef void *cogr_srs = NULL
-+        cdef char **options = NULL
-+        self.collection = collection
-+        cdef char *path_c
-+        cdef char *driver_c
-+        cdef char *name_c
-+        cdef char *proj_c
-+        cdef char *fileencoding_c
-+        path = collection.path
-+
-+        if collection.mode == 'a':
-+            if os.path.exists(path):
-+                try:
-+                    path_b = path.encode('utf-8')
-+                except UnicodeDecodeError:
-+                    path_b = path
-+                path_c = path_b
-+                with cpl_errs:
-+                    self.cogr_ds = ograpi.GDALOpenEx(path_c,
-+                                                 ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_UPDATE,
-+                                                 NULL,
-+                                                 NULL,
-+                                                 NULL)
-+#                     self.cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
-+                if self.cogr_ds == NULL:
-+                    raise RuntimeError("Failed to open %s" % path)
-+                cogr_driver = ograpi.GDALGetDatasetDriver(self.cogr_ds)
-+                if cogr_driver == NULL:
-+                    raise ValueError("Null driver")
-+
-+                if isinstance(collection.name, string_types):
-+                    name_b = collection.name.encode()
-+                    name_c = name_b
-+                    self.cogr_layer = ograpi.GDALDatasetGetLayerByName(
-+                                        self.cogr_ds, name_c)
-+                elif isinstance(collection.name, int):
-+                    self.cogr_layer = ograpi.GDALDatasetGetLayer(
-+                                        self.cogr_ds, collection.name)
-+
-+                if self.cogr_layer == NULL:
-+                    raise RuntimeError(
-+                        "Failed to get layer %s" % collection.name)
-+            else:
-+                raise OSError("No such file or directory %s" % path)
-+
-+            userencoding = self.collection.encoding
-+            self._fileencoding = (userencoding or (
-+                ograpi.OGR_L_TestCapability(self.cogr_layer, OLC_STRINGSASUTF8) and
-+                'utf-8') or (
-+                self.get_driver() == "ESRI Shapefile" and
-+                'ISO-8859-1') or locale.getpreferredencoding()).upper()
-+
-+        elif collection.mode == 'w':
-+            try:
-+                path_b = path.encode('utf-8')
-+            except UnicodeDecodeError:
-+                path_b = path
-+            path_c = path_b
-+            driver_b = collection.driver.encode()
-+            driver_c = driver_b
-+
-+            cogr_driver = ograpi.GDALGetDriverByName(driver_c)
-+            if cogr_driver == NULL:
-+                raise ValueError("Null driver")
-+
-+            if not os.path.exists(path):
-+#                 cogr_ds = ograpi.OGR_Dr_CreateDataSource(
-+#                     cogr_driver, path_c, NULL)
-+                cogr_ds = ograpi.GDALCreate(
-+                    cogr_driver,
-+                    path_c,
-+                    0,
-+                    0,
-+                    0,
-+                    ograpi.GDT_Unknown,
-+                    NULL)
-+                pass
-+
-+            else:
-+                with cpl_errs:
-+                    cogr_ds = ograpi.GDALOpenEx(path_c,
-+                                     ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_UPDATE,
-+                                     NULL,
-+                                     NULL,
-+                                     NULL)
-+#                     cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
-+                if cogr_ds == NULL:
-+                    cogr_ds = ograpi.GDALCreate(
-+                        cogr_driver,
-+                        path_c,
-+                        0,
-+                        0,
-+                        0,
-+                        ograpi.GDT_Unknown,
-+                        NULL)
-+#                     cogr_ds = ograpi.OGR_Dr_CreateDataSource(
-+#                         cogr_driver, path_c, NULL)
-+
-+                elif collection.name is None:
-+                    ograpi.GDALClose(cogr_ds)
-+                    cogr_ds == NULL
-+                    log.debug("Deleted pre-existing data at %s", path)
-+                    cogr_ds = ograpi.GDALCreate(
-+                        cogr_driver,
-+                        path_c,
-+                        0,
-+                        0,
-+                        0,
-+                        ograpi.GDT_Unknown,
-+                        NULL)
-+#                     cogr_ds = ograpi.OGR_Dr_CreateDataSource(
-+#                         cogr_driver, path_c, NULL)
-+
-+                else:
-+                    pass
-+
-+            if cogr_ds == NULL:
-+                raise RuntimeError("Failed to open %s" % path)
-+            else:
-+                self.cogr_ds = cogr_ds
-+
-+            # Set the spatial reference system from the crs given to the
-+            # collection constructor. We by-pass the crs_wkt and crs
-+            # properties because they aren't accessible until the layer
-+            # is constructed (later).
-+            col_crs = collection._crs_wkt or collection._crs
-+            if col_crs:
-+                cogr_srs = ograpi.OSRNewSpatialReference(NULL)
-+                if cogr_srs == NULL:
-+                    raise ValueError("NULL spatial reference")
-+                # First, check for CRS strings like "EPSG:3857".
-+                if isinstance(col_crs, string_types):
-+                    proj_b = col_crs.encode('utf-8')
-+                    proj_c = proj_b
-+                    ograpi.OSRSetFromUserInput(cogr_srs, proj_c)
-+                elif isinstance(col_crs, dict):
-+                    # EPSG is a special case.
-+                    init = col_crs.get('init')
-+                    if init:
-+                        log.debug("Init: %s", init)
-+                        auth, val = init.split(':')
-+                        if auth.upper() == 'EPSG':
-+                            log.debug("Setting EPSG: %s", val)
-+                            ograpi.OSRImportFromEPSG(cogr_srs, int(val))
-+                    else:
-+                        params = []
-+                        col_crs['wktext'] = True
-+                        for k, v in col_crs.items():
-+                            if v is True or (k in ('no_defs', 'wktext') and v):
-+                                params.append("+%s" % k)
-+                            else:
-+                                params.append("+%s=%s" % (k, v))
-+                        proj = " ".join(params)
-+                        log.debug("PROJ.4 to be imported: %r", proj)
-+                        proj_b = proj.encode('utf-8')
-+                        proj_c = proj_b
-+                        ograpi.OSRImportFromProj4(cogr_srs, proj_c)
-+                else:
-+                    raise ValueError("Invalid CRS")
-+
-+                # Fixup, export to WKT, and set the GDAL dataset's projection.
-+                ograpi.OSRFixup(cogr_srs)
-+
-+            # Figure out what encoding to use. The encoding parameter given
-+            # to the collection constructor takes highest precedence, then
-+            # 'iso-8859-1', then the system's default encoding as last resort.
-+            sysencoding = locale.getpreferredencoding()
-+            userencoding = collection.encoding
-+            self._fileencoding = (userencoding or (
-+                collection.driver == "ESRI Shapefile" and
-+                'ISO-8859-1') or sysencoding).upper()
-+
-+            fileencoding = self.get_fileencoding()
-+            if fileencoding:
-+                fileencoding_b = fileencoding.encode()
-+                fileencoding_c = fileencoding_b
-+                options = ograpi.CSLSetNameValue(options, "ENCODING", fileencoding_c)
-+
-+            # Does the layer exist already? If so, we delete it.
-+            layer_count = ograpi.GDALDatasetGetLayerCount(self.cogr_ds)
-+            layer_names = []
-+            for i in range(layer_count):
-+                cogr_layer = ograpi.GDALDatasetGetLayer(cogr_ds, i)
-+                name_c = ograpi.OGR_L_GetName(cogr_layer)
-+                name_b = name_c
-+                layer_names.append(name_b.decode('utf-8'))
-+
-+            idx = -1
-+            if isinstance(collection.name, string_types):
-+                if collection.name in layer_names:
-+                    idx = layer_names.index(collection.name)
-+            elif isinstance(collection.name, int):
-+                if collection.name >= 0 and collection.name < layer_count:
-+                    idx = collection.name
-+            if idx >= 0:
-+                log.debug("Deleted pre-existing layer at %s", collection.name)
-+                ograpi.GDALDatasetDeleteLayer(self.cogr_ds, idx)
-+            
-+            # Create the named layer in the datasource.
-+            name_b = collection.name.encode('utf-8')
-+            name_c = name_b
-+            self.cogr_layer = ograpi.GDALDatasetCreateLayer(
-+                self.cogr_ds, 
-+                name_c,
-+                cogr_srs,
-+                <unsigned int>[k for k,v in GEOMETRY_TYPES.items() if 
-+                    v == collection.schema.get('geometry', 'Unknown')][0],
-+                options
-+                )
-+
-+            if cogr_srs != NULL:
-+                ograpi.OSRDestroySpatialReference(cogr_srs)
-+            if options != NULL:
-+                ograpi.CSLDestroy(options)
-+
-+            if self.cogr_layer == NULL:
-+                raise ValueError("Null layer")
-+            log.debug("Created layer")
-+            
-+            # Next, make a layer definition from the given schema properties,
-+            # which are an ordered dict since Fiona 1.0.1.
-+            for key, value in collection.schema['properties'].items():
-+                log.debug("Creating field: %s %s", key, value)
-+
-+                # Convert 'long' to 'int'. See
-+                # https://github.com/Toblerity/Fiona/issues/101.
-+                if value == 'long':
-+                    value = 'int'
-+
-+                # Is there a field width/precision?
-+                width = precision = None
-+                if ':' in value:
-+                    value, fmt = value.split(':')
-+                    if '.' in fmt:
-+                        width, precision = map(int, fmt.split('.'))
-+                    else:
-+                        width = int(fmt)
-+
-+                field_type = FIELD_TYPES.index(value)
-+                # See https://trac.osgeo.org/gdal/wiki/rfc31_ogr_64
-+                if value == 'int' and (width is not None and width >= 10):
-+                    field_type = 12
-+
-+                encoding = self.get_internalencoding()
-+                key_bytes = key.encode(encoding)
-+
-+                cogr_fielddefn = ograpi.OGR_Fld_Create(
-+                    key_bytes,
-+                    field_type)
-+                if cogr_fielddefn == NULL:
-+                    raise ValueError("Null field definition")
-+                if width:
-+                    ograpi.OGR_Fld_SetWidth(cogr_fielddefn, width)
-+                if precision:
-+                    ograpi.OGR_Fld_SetPrecision(cogr_fielddefn, precision)
-+                ograpi.OGR_L_CreateField(self.cogr_layer, cogr_fielddefn, 1)
-+                ograpi.OGR_Fld_Destroy(cogr_fielddefn)
-+            log.debug("Created fields")
-+
-+        # Mapping of the Python collection schema to the munged 
-+        # OGR schema.
-+        ogr_schema = self.get_schema()
-+        self._schema_mapping = dict(zip(
-+            collection.schema['properties'].keys(), 
-+            ogr_schema['properties'].keys() ))
-+
-+        log.debug("Writing started")
-+
-+    def writerecs(self, records, collection):
-+        """Writes buffered records to OGR."""
-+        cdef void *cogr_driver
-+        cdef void *cogr_feature
-+
-+        cdef void *cogr_layer = self.cogr_layer
-+        if cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+    
-+        schema_geom_type = collection.schema['geometry']
-+        cogr_driver = ograpi.GDALGetDatasetDriver(self.cogr_ds)
-+        if ograpi.OGR_Dr_GetName(cogr_driver) == b"GeoJSON":
-+            def validate_geometry_type(rec):
-+                return True
-+        elif ograpi.OGR_Dr_GetName(cogr_driver) == b"ESRI Shapefile" \
-+                and "Point" not in collection.schema['geometry']:
-+            schema_geom_type = collection.schema['geometry'].lstrip(
-+                "3D ").lstrip("Multi")
-+            def validate_geometry_type(rec):
-+                return rec['geometry'] is None or \
-+                rec['geometry']['type'].lstrip(
-+                    "3D ").lstrip("Multi") == schema_geom_type
-+        else:
-+            schema_geom_type = collection.schema['geometry'].lstrip("3D ")
-+            def validate_geometry_type(rec):
-+                return rec['geometry'] is None or \
-+                       rec['geometry']['type'].lstrip("3D ") == schema_geom_type
-+
-+        schema_props_keys = set(collection.schema['properties'].keys())
-+        for record in records:
-+            log.debug("Creating feature in layer: %s" % record)
-+            # Validate against collection's schema.
-+            if set(record['properties'].keys()) != schema_props_keys:
-+                raise ValueError(
-+                    "Record does not match collection schema: %r != %r" % (
-+                        record['properties'].keys(), 
-+                        list(schema_props_keys) ))
-+            if not validate_geometry_type(record):
-+                raise ValueError(
-+                    "Record's geometry type does not match "
-+                    "collection schema's geometry type: %r != %r" % (
-+                         record['geometry']['type'],
-+                         collection.schema['geometry'] ))
-+
-+            cogr_feature = OGRFeatureBuilder().build(record, collection)
-+            result = ograpi.OGR_L_CreateFeature(cogr_layer, cogr_feature)
-+            if result != OGRERR_NONE:
-+                raise RuntimeError("Failed to write record: %s" % record)
-+            _deleteOgrFeature(cogr_feature)
-+
-+    def sync(self, collection):
-+        """Syncs OGR to disk."""
-+        cdef void *cogr_ds = self.cogr_ds
-+        cdef void *cogr_layer = self.cogr_layer
-+        if cogr_ds == NULL:
-+            raise ValueError("Null data source")
-+        log.debug("Syncing OGR to disk")
-+
-+        ograpi.GDALFlushCache(cogr_ds)
-+
-+
-+cdef class Iterator:
-+
-+    """Provides iterated access to feature data.
-+    """
-+
-+    # Reference to its Collection
-+    cdef collection
-+    cdef encoding
-+    cdef int next_index
-+    cdef stop
-+    cdef start
-+    cdef step
-+    cdef fastindex
-+    cdef stepsign
-+
-+    def __init__(self, collection, 
-+            start=None, stop=None, step=None, bbox=None, mask=None):
-+        if collection.session is None:
-+            raise ValueError("I/O operation on closed collection")
-+        self.collection = collection
-+        cdef Session session
-+        cdef void *cogr_geometry
-+        session = self.collection.session
-+        cdef void *cogr_layer = session.cogr_layer
-+        if cogr_layer == NULL:
-+            raise ValueError("Null layer")
-+        ograpi.OGR_L_ResetReading(cogr_layer)
-+        
-+        if bbox and mask:
-+            raise ValueError("mask and bbox can not be set together")
-+        
-+        if bbox:
-+            ograpi.OGR_L_SetSpatialFilterRect(
-+                cogr_layer, bbox[0], bbox[1], bbox[2], bbox[3])
-+        elif mask:
-+            cogr_geometry = OGRGeomBuilder().build(mask)
-+            ograpi.OGR_L_SetSpatialFilter(cogr_layer, cogr_geometry)
-+            ograpi.OGR_G_DestroyGeometry(cogr_geometry)
-+            
-+        else:
-+            ograpi.OGR_L_SetSpatialFilter(
-+                cogr_layer, NULL)
-+        self.encoding = session.get_internalencoding()
-+
-+        self.fastindex = ograpi.OGR_L_TestCapability(
-+            session.cogr_layer, OLC_FASTSETNEXTBYINDEX)
-+
-+        ftcount = ograpi.OGR_L_GetFeatureCount(session.cogr_layer, 0)
-+        if ftcount == -1 and ((start is not None and start < 0) or
-+                              (stop is not None and stop < 0)):
-+            raise IndexError(
-+                "collection's dataset does not support negative slice indexes")
-+
-+        if stop is not None and stop < 0:
-+            stop += ftcount
-+
-+        if start is None:
-+            start = 0
-+        if start is not None and start < 0:
-+            start += ftcount
-+
-+        # step size
-+        if step is None:
-+            step = 1
-+        if step == 0:
-+            raise ValueError("slice step cannot be zero")
-+        if step < 0 and not self.fastindex:
-+            warnings.warn("Layer does not support" \
-+                    "OLCFastSetNextByIndex, negative step size may" \
-+                    " be slow", RuntimeWarning)
-+        self.stepsign = int(math.copysign(1, step))
-+        self.stop = stop
-+        self.start = start
-+        self.step = step
-+
-+        self.next_index = start
-+        log.debug("Index: %d", self.next_index)
-+        ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+
-+
-+    def __iter__(self):
-+        return self
-+
-+
-+    def _next(self):
-+        """Internal method to set read cursor to next item"""
-+
-+        cdef Session session
-+        session = self.collection.session
-+
-+        # Check if next_index is valid
-+        if self.next_index < 0:
-+            raise StopIteration
-+        
-+        if self.stepsign == 1:
-+            if self.next_index < self.start or (self.stop is not None and self.next_index >= self.stop):
-+                raise StopIteration
-+        else:
-+            if self.next_index > self.start or (self.stop is not None and self.next_index <= self.stop):
-+                raise StopIteration
-+
-+
-+        # Set read cursor to next_item position
-+        if self.step > 1 and self.fastindex:
-+            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+
-+        elif self.step > 1 and not self.fastindex and not self.next_index == self.start:
-+            for _ in range(self.step - 1):
-+                # TODO rbuffat add test -> OGR_L_GetNextFeature increments cursor by 1, therefore self.step - 1 as one increment was performed when feature is read
-+                cogr_feature = ograpi.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:
-+            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+
-+        elif self.step == 0:
-+            # ograpi.OGR_L_GetNextFeature increments read cursor by one
-+            pass
-+        elif self.step < 0:
-+            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
-+            
-+        # set the next index
-+        self.next_index += self.step
-+
-+
-+    def __next__(self):
-+        cdef void * cogr_feature
-+        cdef Session session
-+        session = self.collection.session
-+
-+        #Update read cursor
-+        self._next()
-+
-+        # Get the next feature.
-+        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
-+        if cogr_feature == NULL:
-+            raise StopIteration
-+
-+        feature = FeatureBuilder().build(
-+            cogr_feature,
-+            bbox=False,
-+            encoding=self.encoding,
-+            driver=self.collection.driver
-+        )
-+        _deleteOgrFeature(cogr_feature)
-+        return feature
-+
-+
-+cdef class ItemsIterator(Iterator):
-+
-+    def __next__(self):
-+
-+        cdef long fid
-+        cdef void * cogr_feature
-+        cdef Session session
-+        session = self.collection.session
-+
-+        #Update read cursor
-+        self._next()
-+
-+        # Get the next feature.
-+        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
-+        if cogr_feature == NULL:
-+            raise StopIteration
-+
-+
-+        fid = ograpi.OGR_F_GetFID(cogr_feature)
-+        feature = FeatureBuilder().build(
-+            cogr_feature,
-+            bbox=False,
-+            encoding=self.encoding,
-+            driver=self.collection.driver
-+        )
-+        _deleteOgrFeature(cogr_feature)
-+
-+        return fid, feature
-+
-+
-+cdef class KeysIterator(Iterator):
-+
-+    def __next__(self):
-+        cdef long fid
-+        cdef void * cogr_feature
-+        cdef Session session
-+        session = self.collection.session
-+
-+        #Update read cursor
-+        self._next()
-+
-+        # Get the next feature.
-+        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
-+        if cogr_feature == NULL:
-+            raise StopIteration
-+
-+        fid = ograpi.OGR_F_GetFID(cogr_feature)
-+        _deleteOgrFeature(cogr_feature)
-+
-+        return fid
-+
-+
-+def _listlayers(path):
-+
-+    """Provides a list of the layers in an OGR data source.
-+    """
-+    
-+    cdef void *cogr_ds
-+    cdef void *cogr_layer
-+    cdef char *path_c
-+    cdef char *name_c
-+    
-+    # Open OGR data source.
-+    try:
-+        path_b = path.encode('utf-8')
-+    except UnicodeDecodeError:
-+        path_b = path
-+    path_c = path_b
-+    with cpl_errs:
-+        cogr_ds = ograpi.GDALOpenEx(path_c,
-+             ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_READONLY,
-+             NULL,
-+             NULL,
-+             NULL)
-+#         cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
-+    if cogr_ds == NULL:
-+        raise ValueError("No data available at path '%s'" % path)
-+    
-+    # Loop over the layers to get their names.
-+    layer_count = ograpi.GDALDatasetGetLayerCount(cogr_ds)
-+    layer_names = []
-+    for i in range(layer_count):
-+        cogr_layer = ograpi.GDALDatasetGetLayer(cogr_ds, i)
-+        name_c = ograpi.OGR_L_GetName(cogr_layer)
-+        name_b = name_c
-+        layer_names.append(name_b.decode('utf-8'))
-+    
-+    # Close up data source.
-+    if cogr_ds is not NULL:
-+        ograpi.GDALClose(cogr_ds)
-+    cogr_ds = NULL
-+
-+    return layer_names
-+
-+def buffer_to_virtual_file(bytesbuf):
-+    """Maps a bytes buffer to a virtual file.
-+    """
-+    vsi_filename = os.path.join('/vsimem', uuid.uuid4().hex)
-+    vsi_cfilename = vsi_filename if not isinstance(vsi_filename, string_types) else vsi_filename.encode('utf-8')
-+
-+    vsi_handle = ograpi.VSIFileFromMemBuffer(vsi_cfilename, bytesbuf, len(bytesbuf), 0)
-+    if vsi_handle == NULL:
-+        raise OSError('failed to map buffer to file')
-+    if ograpi.VSIFCloseL(vsi_handle) != 0:
-+        raise OSError('failed to close mapped file handle')
-+
-+    return vsi_filename
-+
-+def remove_virtual_file(vsi_filename):
-+    vsi_cfilename = vsi_filename if not isinstance(vsi_filename, string_types) else vsi_filename.encode('utf-8')
-+    return ograpi.VSIUnlink(vsi_cfilename)
-+
-+
---- a/setup.py
-+++ b/setup.py
-@@ -66,17 +66,34 @@ with open('CREDITS.txt', **open_kwds) as
- with open('CHANGES.txt', **open_kwds) as f:
-     changes = f.read()
- 
-+
-+def copy_gdalapi(gdalversion):
-+    if gdalversion[0] == u'1':
-+        log.info("Building Fiona for gdal 1.x: {}".format(gdal_output[3]))
-+        shutil.copy('fiona/ogrext1.pyx', 'fiona/ogrext.pyx')
-+        shutil.copy('fiona/ograpi1.pxd', 'fiona/ograpi.pxd')
-+    else:
-+        log.info("Building Fiona for gdal 2.x: {}".format(gdal_output[3]))
-+        shutil.copy('fiona/ogrext2.pyx', 'fiona/ogrext.pyx')
-+        shutil.copy('fiona/ograpi2.pxd', 'fiona/ograpi.pxd')
-+ 
-+if '--gdalversion' in sys.argv:
-+    index = sys.argv.index('--gdalversion')
-+    sys.argv.pop(index)
-+    gdalversion = sys.argv.pop(index)
-+    copy_gdalapi(gdalversion)
-+
- # By default we'll try to get options via gdal-config. On systems without,
- # options will need to be set in setup.cfg or on the setup command line.
- include_dirs = []
- library_dirs = []
- libraries = []
- extra_link_args = []
--gdal_output = [None]*3
-+gdal_output = [None] * 4
- 
- try:
-     gdal_config = os.environ.get('GDAL_CONFIG', 'gdal-config')
--    for i, flag in enumerate(("--cflags", "--libs", "--datadir")):
-+    for i, flag in enumerate(("--cflags", "--libs", "--datadir", "--version")):
-         gdal_output[i] = check_output([gdal_config, flag]).strip()
- 
-     for item in gdal_output[0].split():
-@@ -91,6 +108,8 @@ try:
-             # e.g. -framework GDAL
-             extra_link_args.append(item)
- 
-+    copy_gdalapi(gdal_output[3])
-+
- except Exception as e:
-     if os.name == "nt":
-         log.info(("Building on Windows requires extra options to setup.py to locate needed GDAL files.\n"
-@@ -131,13 +150,14 @@ ext_options = dict(
-     extra_link_args=extra_link_args)
- 
- # When building from a repo, Cython is required.
--if os.path.exists("MANIFEST.in"):
-+if os.path.exists("MANIFEST.in") and "clean" not in sys.argv:
-     log.info("MANIFEST.in found, presume a repo, cythonizing...")
-     if not cythonize:
-         log.critical(
-             "Cython.Build.cythonize not found. "
-             "Cython is required to build from a repo.")
-         sys.exit(1)
-+
-     ext_modules = cythonize([
-         Extension('fiona._geometry', ['fiona/_geometry.pyx'], **ext_options),
-         Extension('fiona._transform', ['fiona/_transform.pyx'], **ext_options),
-@@ -166,8 +186,8 @@ setup_args = dict(
-     metadata_version='1.2',
-     name='Fiona',
-     version=version,
--    requires_python = '>=2.6',
--    requires_external = 'GDAL (>=1.8)',
-+    requires_python='>=2.6',
-+    requires_external='GDAL (>=1.8)',
-     description="Fiona reads and writes spatial data files",
-     license='BSD',
-     keywords='gis vector feature data',
---- a/requirements.txt
-+++ b/requirements.txt
-@@ -2,3 +2,4 @@ argparse
- cligj
- six
- ordereddict
-+munch
---- /dev/null
-+++ b/tests/test_bigint.py
-@@ -0,0 +1,69 @@
-+import fiona
-+import os
-+import shutil
-+import tempfile
-+import unittest
-+from fiona.ogrext import calc_gdal_version_num, get_gdal_version_num
-+
-+"""
-+
-+OGR 54bit handling: https://trac.osgeo.org/gdal/wiki/rfc31_ogr_64
-+
-+Shapefile: OFTInteger fields are created by default with a width of 9
-+characters, so to be unambiguously read as OFTInteger (and if specifying
-+integer that require 10 or 11 characters. the field is dynamically extended
-+like managed since a few versions). OFTInteger64 fields are created by default
-+with a width of 18 digits, so to be unambiguously read as OFTInteger64, and
-+extented to 19 or 20 if needed. Integer fields of width between 10 and 18
-+will be read as OFTInteger64. Above they will be treated as OFTReal. In
-+previous GDAL versions, Integer fields were created with a default with of 10,
-+and thus will be now read as OFTInteger64. An open option, DETECT_TYPE=YES, can
-+be specified so as OGR does a full scan of the DBF file to see if integer
-+fields of size 10 or 11 hold 32 bit or 64 bit values and adjust the type
-+accordingly (and same for integer fields of size 19 or 20, in case of overflow
-+of 64 bit integer, OFTReal is chosen)
-+"""
-+class TestBigInt(unittest.TestCase):
-+
-+    def setUp(self):
-+        self.tempdir = tempfile.mkdtemp()
-+
-+    def tearDown(self):
-+        shutil.rmtree(self.tempdir)
-+
-+    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(src)
-+                    self.assertEqual(first['properties'][fieldname], a_bigint)
-+
-+
-+if __name__ == "__main__":
-+    # import sys;sys.argv = ['', 'Test.testName']
-+    unittest.main()
---- a/tests/test_props.py
-+++ b/tests/test_props.py
-@@ -22,8 +22,8 @@ def test_width_other():
- def test_types():
-     assert prop_type('str:254') == text_type
-     assert prop_type('str') == text_type
--    assert prop_type('int') == type(0)
--    assert prop_type('float') == type(0.0)
-+    assert isinstance(0, prop_type('int'))
-+    assert isinstance(0.0, prop_type('float'))
-     assert prop_type('date') == FionaDateType
- 
- 
---- /dev/null
-+++ b/.gitignore
-@@ -0,0 +1,69 @@
-+# Byte-compiled / optimized / DLL files
-+__pycache__/
-+*.py[cod]
-+
-+# C extensions
-+*.so
-+
-+# Distribution / packaging
-+.Python
-+env/
-+build/
-+develop-eggs/
-+dist/
-+downloads/
-+eggs/
-+.eggs/
-+lib/
-+lib64/
-+parts/
-+sdist/
-+var/
-+*.egg-info/
-+.installed.cfg
-+*.egg
-+
-+# PyInstaller
-+#  Usually these files are written by a python script from a template
-+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-+*.manifest
-+*.spec
-+
-+# Installer logs
-+pip-log.txt
-+pip-delete-this-directory.txt
-+
-+# Unit test / coverage reports
-+htmlcov/
-+.tox/
-+.coverage
-+.coverage.*
-+.cache
-+nosetests.xml
-+coverage.xml
-+*,cover
-+
-+# Translations
-+*.mo
-+*.pot
-+
-+# Django stuff:
-+*.log
-+
-+# Sphinx documentation
-+docs/_build/
-+
-+# PyBuilder
-+target/
-+
-+# IDE's etc.
-+.idea/
-+venv/
-+venv2/
-+
-+#fiona
-+fiona/ogrext.c
-+fiona/_drivers.c
-+fiona/_err.c
-+fiona/_geometry.c
-+fiona/_transform.cpp
---- a/README.rst
-+++ b/README.rst
-@@ -236,7 +236,7 @@ gdal``).
- Python Requirements
- -------------------
- 
--Fiona depends on the modules ``six``, ``cligj``, ``argparse``, and
-+Fiona depends on the modules ``six``, ``cligj``,  ``future``,  ``munch``, ``argparse``, and
- ``ordereddict`` (the two latter modules are standard in Python 2.7+). Pip will
- fetch these requirements for you, but users installing Fiona from a Windows
- installer must get them separately.
-@@ -314,7 +314,7 @@ locations on your system (via your syste
- If you have a non-standard environment, you'll need to specify the include and
- lib dirs and GDAL library on the command line::
- 
--  (fiona_env)$ python setup.py build_ext -I/path/to/gdal/include -L/path/to/gdal/lib -lgdal develop
-+  (fiona_env)$ python setup.py build_ext -I/path/to/gdal/include -L/path/to/gdal/lib -lgdal --gdalversion 2.0.1 develop
-   (fiona_env)$ nosetests
- 
- .. _OGR: http://www.gdal.org/ogr
---- a/requirements-dev.txt
-+++ b/requirements-dev.txt
-@@ -1,3 +1,4 @@
-+-r requirements.txt
- cython>=0.21.2
- nose
- pytest
diff --git a/debian/patches/0004-Just-use-int-as-a-plain-old-builtin.patch b/debian/patches/0004-Just-use-int-as-a-plain-old-builtin.patch
deleted file mode 100644
index 2b74377..0000000
--- a/debian/patches/0004-Just-use-int-as-a-plain-old-builtin.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-Origin: https://github.com/Toblerity/Fiona/commit/805bb6224df389d493cee5b933a65f5b9e4026c9
-From c1b7189bfd5f1613eea017e474034a6a5f56827a Mon Sep 17 00:00:00 2001
-From: Sean Gillies <sean at mapbox.com>
-Date: Tue, 27 Oct 2015 13:04:39 -0600
-Subject: [PATCH] Just use int as a plain old builtin
-
----
- README.rst        | 2 +-
- fiona/ogrext2.pyx | 5 -----
- 2 files changed, 1 insertion(+), 6 deletions(-)
-
---- a/README.rst
-+++ b/README.rst
-@@ -236,7 +236,7 @@ gdal``).
- Python Requirements
- -------------------
- 
--Fiona depends on the modules ``six``, ``cligj``,  ``future``,  ``munch``, ``argparse``, and
-+Fiona depends on the modules ``six``, ``cligj``,  ``munch``, ``argparse``, and
- ``ordereddict`` (the two latter modules are standard in Python 2.7+). Pip will
- fetch these requirements for you, but users installing Fiona from a Windows
- installer must get them separately.
---- a/fiona/ogrext2.pyx
-+++ b/fiona/ogrext2.pyx
-@@ -10,11 +10,6 @@ import warnings
- import math
- import uuid
- 
--if sys.version_info > (3,):
--    from builtins import int
--else:
--    from __builtin__ import int
--
- from six import integer_types, string_types, text_type
- 
- from fiona cimport ograpi
diff --git a/debian/patches/0005-Initial-attempt-at-fiona.remove-for-deleting-data-sources.patch b/debian/patches/0005-Initial-attempt-at-fiona.remove-for-deleting-data-sources.patch
deleted file mode 100644
index cae6f00..0000000
--- a/debian/patches/0005-Initial-attempt-at-fiona.remove-for-deleting-data-sources.patch
+++ /dev/null
@@ -1,246 +0,0 @@
-From d8fcdeb95e10de9a1c8a6d2fbdcd5b8e861ae725 Mon Sep 17 00:00:00 2001
-From: Joshua Arnott <josh at snorfalorpagus.net>
-Date: Tue, 27 Oct 2015 23:40:38 +0000
-Subject: [PATCH 1/6] Initial attempt at fiona.remove from deleting data
- sources
-
----
- fiona/__init__.py | 12 +++++++++++-
- fiona/ogrext1.pyx | 18 ++++++++++++++++++
- 2 files changed, 29 insertions(+), 1 deletion(-)
-
---- a/fiona/__init__.py
-+++ b/fiona/__init__.py
-@@ -69,7 +69,7 @@ from six import string_types
- from fiona.collection import Collection, BytesCollection, vsi_path
- from fiona._drivers import driver_count, GDALEnv, supported_drivers
- from fiona.odict import OrderedDict
--from fiona.ogrext import _bounds, _listlayers, FIELD_TYPES_MAP
-+from fiona.ogrext import _bounds, _listlayers, FIELD_TYPES_MAP, _remove
- from fiona.ogrext import (
-     calc_gdal_version_num, get_gdal_version_num, get_gdal_release_name)
- import warnings
-@@ -191,6 +191,33 @@ def open(
- collection = open
- 
- 
-+def remove(path_or_collection, driver=None):
-+    """Deletes an OGR data source
-+
-+    The required ``path`` argument may be an absolute or relative file path.
-+    Alternatively, a Collection can be passed instead in which case the path
-+    and driver are automatically determined. Otherwise the ``driver`` argument
-+    must be specified.
-+
-+    Raises a ``RuntimeError`` if the data source cannot be deleted.
-+
-+    Example usage:
-+
-+      fiona.remove('test.shp', 'ESRI Shapefile')
-+
-+    """
-+    if isinstance(path_or_collection, Collection):
-+        collection = path_or_collection
-+        path = collection.path
-+        driver = collection.driver
-+        collection.close()
-+    else:
-+        path = path_or_collection
-+        if driver is None:
-+            raise ValueError("The driver argument is required when removing a path")
-+    _remove(path, driver)
-+
-+
- def listlayers(path, vfs=None):
-     """Returns a list of layer names in their index order.
-     
---- a/fiona/ogrext1.pyx
-+++ b/fiona/ogrext1.pyx
-@@ -61,6 +61,10 @@ FIELD_TYPES_MAP = {
-     'datetime': FionaDateTimeType
-    }
- 
-+# OGR Driver capability
-+ODrCCreateDataSource = b"CreateDataSource"
-+ODrCDeleteDataSource = b"DeleteDataSource"
-+
- # OGR Layer capability
- OLC_RANDOMREAD = b"RandomRead"
- OLC_SEQUENTIALWRITE = b"SequentialWrite"
-@@ -1173,6 +1177,27 @@ cdef class KeysIterator(Iterator):
-         return fid
- 
- 
-+def _remove(path, driver=None):
-+    """Deletes an OGR data source
-+    """
-+    cdef void *cogr_driver
-+    cdef int result
-+
-+    if driver is None:
-+        driver = 'ESRI Shapefile'
-+
-+    cogr_driver = ograpi.OGRGetDriverByName(driver.encode('utf-8'))
-+    if cogr_driver == NULL:
-+        raise ValueError("Null driver")
-+
-+    if not ograpi.OGR_Dr_TestCapability(cogr_driver, ODrCDeleteDataSource):
-+        raise RuntimeError("Driver does not support dataset removal operation")
-+
-+    result = ograpi.OGR_Dr_DeleteDataSource(cogr_driver, path.encode('utf-8'))
-+    if result != OGRERR_NONE:
-+        raise RuntimeError("Failed to remove data source {}".format(path))
-+
-+
- def _listlayers(path):
- 
-     """Provides a list of the layers in an OGR data source.
---- /dev/null
-+++ b/tests/test_remove.py
-@@ -0,0 +1,77 @@
-+import logging
-+import sys
-+import os
-+
-+import tempfile
-+import pytest
-+
-+import fiona
-+
-+
-+logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
-+
-+
-+def create_sample_data(filename, driver):
-+    meta = {
-+        'driver': driver,
-+        'schema': {
-+            'geometry': 'Point',
-+            'properties': {}
-+        }
-+    }
-+    with fiona.open(filename, 'w', **meta) as dst:
-+        dst.write({
-+            'geometry': {
-+                'type': 'Point',
-+                'coordinates': (0, 0),
-+            },
-+            'properties': {},
-+        })
-+    assert(os.path.exists(filename))
-+
-+
-+def test_remove(tmpdir=None):
-+    if tmpdir is None:
-+        tmpdir = tempfile.mkdtemp()
-+    filename_shp = os.path.join(tmpdir, 'test.shp')
-+    
-+    create_sample_data(filename_shp, driver='ESRI Shapefile')
-+    fiona.remove(filename_shp, driver='ESRI Shapefile')
-+    assert(not os.path.exists(filename_shp))
-+    
-+    with pytest.raises(RuntimeError):
-+        fiona.remove(filename_shp, driver='ESRI Shapefile')
-+
-+def test_remove_driver(tmpdir=None):
-+    if tmpdir is None:
-+        tmpdir = tempfile.mkdtemp()
-+    filename_shp = os.path.join(tmpdir, 'test.shp')
-+    filename_json = os.path.join(tmpdir, 'test.json')
-+        
-+    create_sample_data(filename_shp, driver='ESRI Shapefile')
-+    create_sample_data(filename_json, driver='GeoJSON')
-+    fiona.remove(filename_json, driver='GeoJSON')
-+    assert(not os.path.exists(filename_json))
-+    assert(os.path.exists(filename_shp))
-+
-+def test_remove_collection(tmpdir=None):
-+    if tmpdir is None:
-+        tmpdir = tempfile.mkdtemp()
-+    filename_shp = os.path.join(tmpdir, 'test.shp')
-+    
-+    create_sample_data(filename_shp, driver='ESRI Shapefile')
-+    collection = fiona.open(filename_shp, 'r')
-+    fiona.remove(collection)
-+    assert(not os.path.exists(filename_shp))
-+
-+def test_remove_path_without_driver(tmpdir=None):
-+    if tmpdir is None:
-+        tmpdir = tempfile.mkdtemp()
-+    filename_shp = os.path.join(tmpdir, 'test.shp')
-+
-+    create_sample_data(filename_shp, driver='ESRI Shapefile')
-+
-+    with pytest.raises(Exception):
-+        fiona.remove(filename_shp)
-+
-+    assert(os.path.exists(filename_shp))
---- a/fiona/ogrext2.pyx
-+++ b/fiona/ogrext2.pyx
-@@ -64,6 +64,10 @@ FIELD_TYPES_MAP = {
-     'datetime': FionaDateTimeType
-    }
- 
-+# OGR Driver capability
-+ODrCCreateDataSource = b"CreateDataSource"
-+ODrCDeleteDataSource = b"DeleteDataSource"
-+
- # OGR Layer capability
- OLC_RANDOMREAD = b"RandomRead"
- OLC_SEQUENTIALWRITE = b"SequentialWrite"
-@@ -1244,6 +1248,27 @@ cdef class KeysIterator(Iterator):
-         return fid
- 
- 
-+def _remove(path, driver=None):
-+    """Deletes an OGR data source
-+    """
-+    cdef void *cogr_driver
-+    cdef int result
-+
-+    if driver is None:
-+        driver = 'ESRI Shapefile'
-+
-+    cogr_driver = ograpi.OGRGetDriverByName(driver.encode('utf-8'))
-+    if cogr_driver == NULL:
-+        raise ValueError("Null driver")
-+
-+    if not ograpi.OGR_Dr_TestCapability(cogr_driver, ODrCDeleteDataSource):
-+        raise RuntimeError("Driver does not support dataset removal operation")
-+
-+    result = ograpi.GDALDeleteDataset(cogr_driver, path.encode('utf-8'))
-+    if result != OGRERR_NONE:
-+        raise RuntimeError("Failed to remove data source {}".format(path))
-+
-+
- def _listlayers(path):
- 
-     """Provides a list of the layers in an OGR data source.
---- a/fiona/ograpi2.pxd
-+++ b/fiona/ograpi2.pxd
-@@ -36,6 +36,7 @@ cdef extern from "gdal.h":
-     void GDALFlushCache(void * hDS)
-     char * GDALGetDriverShortName(void * hDriver)
-     char * GDALGetDatasetDriver (void * hDataset)
-+    int GDALDeleteDataset(void * hDriver, const char * pszFilename)
- 
- 
-     ctypedef enum GDALDataType:
-@@ -110,6 +111,7 @@ cdef extern from "ogr_api.h":
-     void *  OGR_Dr_CreateDataSource (void *driver, const char *path, char **options)
-     int     OGR_Dr_DeleteDataSource (void *driver, char *)
-     void *  OGR_Dr_Open (void *driver, const char *path, int bupdate)
-+    int     OGR_Dr_TestCapability (void *driver, const char *)
-     void *  OGR_F_Create (void *featuredefn)
-     void    OGR_F_Destroy (void *feature)
-     long    OGR_F_GetFID (void *feature)
---- a/fiona/ograpi1.pxd
-+++ b/fiona/ograpi1.pxd
-@@ -62,6 +62,7 @@ cdef extern from "ogr_api.h":
-     void *  OGR_Dr_CreateDataSource (void *driver, const char *path, char **options)
-     int     OGR_Dr_DeleteDataSource (void *driver, char *)
-     void *  OGR_Dr_Open (void *driver, const char *path, int bupdate)
-+    int     OGR_Dr_TestCapability (void *driver, const char *)
-     int     OGR_DS_DeleteLayer (void *datasource, int n)
-     void *  OGR_DS_CreateLayer (void *datasource, char *name, void *crs, int geomType, char **options)
-     void *  OGR_DS_ExecuteSQL (void *datasource, char *name, void *filter, char *dialext)
diff --git a/debian/patches/0006-Remove-unknown-distribution-options.patch b/debian/patches/0006-Remove-unknown-distribution-options.patch
index 75848fd..fd1a019 100644
--- a/debian/patches/0006-Remove-unknown-distribution-options.patch
+++ b/debian/patches/0006-Remove-unknown-distribution-options.patch
@@ -6,7 +6,7 @@ Author: Bas Couwenberg <sebastic at debian.org>
 
 --- a/setup.py
 +++ b/setup.py
-@@ -183,11 +183,8 @@ if sys.version_info < (2, 7):
+@@ -180,11 +180,8 @@ if sys.version_info < (2, 7):
      requirements.append('ordereddict')
  
  setup_args = dict(
diff --git a/debian/patches/0007-clean.patch b/debian/patches/0007-clean.patch
deleted file mode 100644
index e7548ad..0000000
--- a/debian/patches/0007-clean.patch
+++ /dev/null
@@ -1,123 +0,0 @@
-Description: Don't copy gdalapi files in clean target.
-Author: Bas Couwenberg <sebastic at debian.org>
-Forwarded: https://github.com/Toblerity/Fiona/pull/322
-Applied-Upstream: https://github.com/Toblerity/Fiona/commit/8f3d471e510bafc3d653387675d1e7999f5c71e7
-
---- a/setup.py
-+++ b/setup.py
-@@ -77,7 +77,7 @@ def copy_gdalapi(gdalversion):
-         shutil.copy('fiona/ogrext2.pyx', 'fiona/ogrext.pyx')
-         shutil.copy('fiona/ograpi2.pxd', 'fiona/ograpi.pxd')
-  
--if '--gdalversion' in sys.argv:
-+if '--gdalversion' in sys.argv and "clean" not in sys.argv:
-     index = sys.argv.index('--gdalversion')
-     sys.argv.pop(index)
-     gdalversion = sys.argv.pop(index)
-@@ -91,57 +91,58 @@ libraries = []
- extra_link_args = []
- gdal_output = [None] * 4
- 
--try:
--    gdal_config = os.environ.get('GDAL_CONFIG', 'gdal-config')
--    for i, flag in enumerate(("--cflags", "--libs", "--datadir", "--version")):
--        gdal_output[i] = check_output([gdal_config, flag]).strip()
--
--    for item in gdal_output[0].split():
--        if item.startswith("-I"):
--            include_dirs.extend(item[2:].split(":"))
--    for item in gdal_output[1].split():
--        if item.startswith("-L"):
--            library_dirs.extend(item[2:].split(":"))
--        elif item.startswith("-l"):
--            libraries.append(item[2:])
-+if "clean" not in sys.argv:
-+    try:
-+        gdal_config = os.environ.get('GDAL_CONFIG', 'gdal-config')
-+        for i, flag in enumerate(("--cflags", "--libs", "--datadir", "--version")):
-+            gdal_output[i] = check_output([gdal_config, flag]).strip()
-+
-+        for item in gdal_output[0].split():
-+            if item.startswith("-I"):
-+                include_dirs.extend(item[2:].split(":"))
-+        for item in gdal_output[1].split():
-+            if item.startswith("-L"):
-+                library_dirs.extend(item[2:].split(":"))
-+            elif item.startswith("-l"):
-+                libraries.append(item[2:])
-+            else:
-+                # e.g. -framework GDAL
-+                extra_link_args.append(item)
-+
-+        copy_gdalapi(gdal_output[3])
-+
-+    except Exception as e:
-+        if os.name == "nt":
-+            log.info(("Building on Windows requires extra options to setup.py to locate needed GDAL files.\n"
-+                       "More information is available in the README."))
-         else:
--            # e.g. -framework GDAL
--            extra_link_args.append(item)
-+            log.warning("Failed to get options via gdal-config: %s", str(e))
- 
--    copy_gdalapi(gdal_output[3])
--
--except Exception as e:
--    if os.name == "nt":
--        log.info(("Building on Windows requires extra options to setup.py to locate needed GDAL files.\n"
--                   "More information is available in the README."))
--    else:
--        log.warning("Failed to get options via gdal-config: %s", str(e))
--
--    # Conditionally copy the GDAL data. To be used in conjunction with
--    # the bdist_wheel command to make self-contained binary wheels.
-+        # Conditionally copy the GDAL data. To be used in conjunction with
-+        # the bdist_wheel command to make self-contained binary wheels.
-+        if os.environ.get('PACKAGE_DATA'):
-+            try:
-+                shutil.rmtree('fiona/gdal_data')
-+            except OSError:
-+                pass
-+            shutil.copytree(datadir, 'fiona/gdal_data')
-     if os.environ.get('PACKAGE_DATA'):
--        try:
--            shutil.rmtree('fiona/gdal_data')
--        except OSError:
--            pass
--        shutil.copytree(datadir, 'fiona/gdal_data')
--if os.environ.get('PACKAGE_DATA'):
--    destdir = 'fiona/gdal_data'
--    if gdal_output[2]:
--        log.info("Copying gdal data from %s" % gdal_output[2])
--        copy_data_tree(gdal_output[2], destdir)
--    else:
--        # check to see if GDAL_DATA is defined
--        gdal_data = os.environ.get('GDAL_DATA', None)
--        if gdal_data:
--            log.info("Copying gdal data from %s" % gdal_data)
--            copy_data_tree(gdal_data, destdir)
--
--    # Conditionally copy PROJ.4 data. 
--    projdatadir = os.environ.get('PROJ_LIB', '/usr/local/share/proj')
--    if os.path.exists(projdatadir):
--        log.info("Copying proj data from %s" % projdatadir)
--        copy_data_tree(projdatadir, 'fiona/proj_data')
-+        destdir = 'fiona/gdal_data'
-+        if gdal_output[2]:
-+            log.info("Copying gdal data from %s" % gdal_output[2])
-+            copy_data_tree(gdal_output[2], destdir)
-+        else:
-+            # check to see if GDAL_DATA is defined
-+            gdal_data = os.environ.get('GDAL_DATA', None)
-+            if gdal_data:
-+                log.info("Copying gdal data from %s" % gdal_data)
-+                copy_data_tree(gdal_data, destdir)
-+
-+        # Conditionally copy PROJ.4 data. 
-+        projdatadir = os.environ.get('PROJ_LIB', '/usr/local/share/proj')
-+        if os.path.exists(projdatadir):
-+            log.info("Copying proj data from %s" % projdatadir)
-+            copy_data_tree(projdatadir, 'fiona/proj_data')
- 
- ext_options = dict(
-     include_dirs=include_dirs,
diff --git a/debian/patches/0008-Disable-GDAL-2-ImportError.patch b/debian/patches/0008-Disable-GDAL-2-ImportError.patch
deleted file mode 100644
index 4d6aec6..0000000
--- a/debian/patches/0008-Disable-GDAL-2-ImportError.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-Description: Disable ImportError for GDAL 2.x.
- GDAL 2.x changes backported from Fiona 1.7.
-Author: Bas Couwenberg <sebastic at debian.org>
-Forwarded: not-needed
-
---- a/fiona/__init__.py
-+++ b/fiona/__init__.py
-@@ -84,12 +84,6 @@ __all__ = ['bounds', 'listlayers', 'open
- __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):
diff --git a/debian/patches/series b/debian/patches/series
index 3b6d427..780dd7b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,8 +1,3 @@
 0001-Rename-fio-command-to-fiona-to-avoid-name-clash.patch
 0002-Remove-outside-reference-possible-privacy-breach.patch
-0003-GDAL-2.0.patch
-0004-Just-use-int-as-a-plain-old-builtin.patch
-0005-Initial-attempt-at-fiona.remove-for-deleting-data-sources.patch
 0006-Remove-unknown-distribution-options.patch
-0007-clean.patch
-0008-Disable-GDAL-2-ImportError.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/fiona.git



More information about the Pkg-grass-devel mailing list