[fiona] 01/05: Imported Upstream version 1.7.0

Bas Couwenberg sebastic at debian.org
Tue Jun 14 22:35:41 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 c7f24add24bce7e0431e4b48538b4e8653075ded
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Wed Jun 15 00:05:17 2016 +0200

    Imported Upstream version 1.7.0
---
 .travis.yml                        |   8 +-
 CHANGES.txt                        |  26 +++-
 CREDITS.txt                        |   1 +
 MANIFEST.in                        |  13 +-
 README.rst                         |  21 +--
 appveyor.yml                       |  99 ++++++++++++
 appveyor/install.ps1               | 229 ++++++++++++++++++++++++++++
 appveyor/run_with_env.cmd          |  88 +++++++++++
 fiona/__init__.py                  |   2 +-
 fiona/_cpl.pxd                     |   6 +-
 fiona/_crs.pxd                     |   2 +
 fiona/_crs.pyx                     |  14 +-
 fiona/_csl.pxd                     |   5 +
 fiona/_geometry.pxd                |  33 ++++
 fiona/_geometry.pyx                |  44 +++---
 fiona/_transform.pyx               |  59 ++++----
 fiona/fio/cat.py                   |  64 +++++---
 fiona/fio/dump.py                  |   9 +-
 fiona/fio/options.py               |  30 +++-
 fiona/{ograpi1.pxd => ogrext1.pxd} |   0
 fiona/ogrext1.pyx                  | 270 ++++++++++++++++-----------------
 fiona/{ograpi2.pxd => ogrext2.pxd} |   0
 fiona/ogrext2.pyx                  | 302 ++++++++++++++++++-------------------
 setup.py                           |  55 +++++--
 tests/test_bytescollection.py      |  19 ++-
 tests/test_collection.py           |  37 +++--
 tests/test_drivers.py              |   5 +
 tests/test_fio_cat.py              |  33 +++-
 tests/test_fio_collect.py          |   7 +
 tests/test_fio_dump.py             |  14 ++
 tests/test_fio_info.py             |  15 +-
 tests/test_fio_load.py             |  18 ++-
 tests/test_fio_ls.py               |   7 +
 tests/test_geojson.py              |   6 +-
 tests/test_listing.py              |   4 +
 tests/test_multiconxn.py           |   6 +
 tests/test_non_counting_layer.py   |   4 +-
 tests/test_unicode.py              |  14 +-
 38 files changed, 1130 insertions(+), 439 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index d9da6f6..f2b14d0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,10 +42,12 @@ install:
   - "if [ $(gdal-config --version) == \"$GDALVERSION\" ]; then echo \"Using gdal $GDALVERSION\"; else echo \"NOT using gdal $GDALVERSION as expected; aborting\"; exit 1; fi"
   - "pip wheel -r requirements-dev.txt"
   - "pip install -r requirements-dev.txt"
-  - "pip install --upgrade --force-reinstall --global-option=build_ext --global-option='-I$GDALINST/gdal-$GDALVERSION/include' --global-option='-L$GDALINST/gdal-$GDALVERSION/lib' --global-option='-R$GDALINST/gdal-$GDALVERSION/lib' -e .[test]"
+  - "python setup.py sdist"
+  - "pip install --upgrade --force-reinstall --global-option=build_ext --global-option='-I$GDALINST/gdal-$GDALVERSION/include' --global-option='-L$GDALINST/gdal-$GDALVERSION/lib' --global-option='-R$GDALINST/gdal-$GDALVERSION/lib' dist/Fiona*"
   - "fio --version"
+  - "cp -r tests /tmp"
 script: 
-  - nosetests --exclude test_filter_vsi --exclude test_geopackage --exclude test_write_mismatch
-  - coverage run --source=fiona --omit='*.pxd,*.pyx,*/tests/*,*/docs/*,*/examples/*,*/benchmarks/*' -m nose --exclude test_filter_vsi --exclude test_geopackage --exclude test_write_mismatch
+  - "cd /tmp && nosetests --exclude test_filter_vsi --exclude test_geopackage --exclude test_write_mismatch tests"
+  - "cd /tmp && coverage run --source=fiona --omit='*.pxd,*.pyx,*/tests/*,*/docs/*,*/examples/*,*/benchmarks/*' -m nose --exclude test_filter_vsi --exclude test_geopackage --exclude test_write_mismatch tests"
 after_success:
   - coveralls || echo "!! intermittent coveralls failure"
diff --git a/CHANGES.txt b/CHANGES.txt
index 45d2234..f9afad4 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -3,8 +3,32 @@ Changes
 
 All issue numbers are relative to https://github.com/Toblerity/Fiona/issues.
 
-1.7.0 (2016-06-13)
+1.7.0 (2016-06-14)
 ------------------
+
+The C extension modules in this library can now be built and used with either
+a 1.x or 2.x release of the GDAL library. Big thanks to René Buffat for
+leading this effort.
+
+- Refactoring: The `ogrext1.pyx` and `ogrext2.pyx` files now use separate
+  C APIs defined in `ogrext1.pxd` and `ogrex2.pxd`. The other extension
+  modules have been refactored so that they do not depend on either of these
+  modules and use subsets of the GDAL/OGR API compatible with both GDAL 1.x and
+  2.x (#359).
+- Packaging: Source distributions now contain two different sources for the
+  `ogrext` extension module. The `ogrext1.c` file will be used with GDAL 1.x
+  and the `ogrext2.c` file will be used with GDAL 2.x.
+
+1.7b2 (2016-06-13)
+------------------
+
+- New feature: enhancement of the `--layer` option for fio-cat and fio-dump
+  to allow separate layers of one or more multi-layer input files to be
+  selected (#349).
+
+1.7b1 (2016-06-10)
+------------------
+
 - New feature: support for GDAL version 2+ (#259).
 - New feature: a new fio-calc CLI command (#273).
 - New feature: `--layer` options for fio-info (#316) and fio-load (#299).
diff --git a/CREDITS.txt b/CREDITS.txt
index 00c00a4..44e77ff 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -10,6 +10,7 @@ Fiona is written by:
 - Joshua Arnott <josh at snorfalorpagus.net>
 - Kelsey Jordahl <kjordahl at enthought.com>
 - Micah Cochran <micah at micahcochran.net>
+- Simon Norris <snorris at hillcrestgeo.ca>
 - Patrick Young <patrick.mckendree.young at gmail.com>
 - Hannes Gräuler <graeuler at geoplex.de>
 - Johan Van de Wauw <johan.vandewauw at gmail.com>
diff --git a/MANIFEST.in b/MANIFEST.in
index 19e2824..63510dd 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,8 +1,13 @@
-exclude *.txt *.py
-include CHANGES.txt CREDITS.txt LICENSE.txt VERSION.txt README.rst benchmark.py setup.py
-recursive-include docs *.rst *.txt
+global-exclude .DS_Store
+global-exclude *.pyc
 recursive-exclude docs/data *
 recursive-exclude docs/_build *
+exclude MANIFEST.in
+exclude *.txt *.py
+recursive-include docs *.rst *.txt
 recursive-include tests *.py
 recursive-include tests/data *
-exclude MANIFEST.in
+include fiona/*.c fiona/*.cpp
+exclude fiona/ogrext.c
+include CHANGES.txt CREDITS.txt LICENSE.txt VERSION.txt README.rst
+include benchmark.py setup.py requirements.txt
diff --git a/README.rst b/README.rst
index c4cd169..e9331eb 100644
--- a/README.rst
+++ b/README.rst
@@ -260,25 +260,26 @@ install gdal`` using Homebrew on OS X), installation is this simple.
   $ mkdir fiona_env
   $ virtualenv fiona_env
   $ source fiona_env/bin/activate
-  (fiona_env)$ pip install Fiona
+  (fiona_env)$ pip install fiona
 
 If gdal-config is not available or if GDAL/OGR headers and libs aren't
 installed to a well known location, you must set include dirs, library dirs,
 and libraries options via the setup.cfg file or setup command line as shown
-below (using ``git``).
+below (using ``git``). You must also specify the major version of the GDAL API
+(1 or 2) on the setup command line.
 
 .. code-block:: console
 
   (fiona_env)$ git clone git://github.com/Toblerity/Fiona.git
   (fiona_env)$ cd Fiona
-  (fiona_env)$ python setup.py build_ext -I/path/to/gdal/include -L/path/to/gdal/lib -lgdal install
+  (fiona_env)$ python setup.py build_ext -I/path/to/gdal/include -L/path/to/gdal/lib -lgdal install --gdalversion 1
 
-Or specify that build options should be provided by a particular
-gdal-config program.
+Or specify that build options and GDAL API version should be provided by a
+particular gdal-config program.
 
 .. code-block:: console
 
-  (fiona_env)$ GDAL_CONFIG=/path/to/gdal-config pip install .
+  (fiona_env)$ GDAL_CONFIG=/path/to/gdal-config pip install fiona
 
 Windows
 -------
@@ -295,12 +296,12 @@ cannot rely on gdal-config, which is only present on UNIX systems, to discover
 the locations of header files and libraries that Fiona needs to compile its 
 C extensions. On Windows, these paths need to be provided by the user. 
 You will need to find the include files and the library files for gdal and 
-use setup.py as follows.
+use setup.py as follows. You must also specify the major version of the GDAL
+API (1 or 2) on the setup command line.
 
 .. code-block:: console
 
-    $ python setup.py build_ext -I<path to gdal include files> -lgdal_i -L<path to gdal library>
-    $ python setup.py install
+    $ python setup.py build_ext -I<path to gdal include files> -lgdal_i -L<path to gdal library> install --gdalversion 1
 
 Note: The GDAL dll (gdal111.dll) and gdal-data directory need to be in your 
 Windows PATH otherwise Fiona will fail to work.
@@ -327,7 +328,7 @@ Or you can use the ``pep-518-install`` script::
 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 --gdalversion 2.0.1 develop
+  (fiona_env)$ python setup.py build_ext -I/path/to/gdal/include -L/path/to/gdal/lib -lgdal --gdalversion 2 develop
   (fiona_env)$ nosetests
 
 .. _OGR: http://www.gdal.org/ogr
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..a7bfb50
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,99 @@
+# Based on appveyor.yml from https://github.com/PDAL/PDAL and https://github.com/ogrisel/python-appveyor-demo
+#
+
+platform: x64
+
+
+environment:
+
+    global:
+        # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
+        # /E:ON and /V:ON options are not enabled in the batch script intepreter
+        # See: http://stackoverflow.com/a/13751649/163740
+        CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
+        GDAL_HOME: "C:\\gdal"
+
+    matrix:
+        # - PYTHON: "C:\\Python27.10-x64"
+        #  PYTHON_VERSION: "2.7.10"
+        #  PYTHON_ARCH: "64"
+
+        - PYTHON: "C:\\Python34-x64"
+          PYTHON_VERSION: "3.4.3"
+          PYTHON_ARCH: "64"
+
+install:
+
+  - ECHO "Filesystem root:"
+  - ps: "ls \"C:/\""
+
+  - ECHO "Installed SDKs:"
+  - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
+
+  # Install Python (from the official .msi of http://python.org) and pip when
+  # not already installed.
+  # - ps: if (-not(Test-Path($env:PYTHON))) { & appveyor\install.ps1 }
+
+  # Prepend newly installed Python to the PATH of this build (this cannot be
+  # done from inside the powershell script as it would require to restart
+  # the parent CMD process).
+  - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
+  - "SET PYTHONPATH=%PYTHON%\\Lib\\site-packages;%PYTHONPATH%"
+
+  # Check that we have the expected version and architecture for Python
+  - "python --version"
+  - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
+
+  
+  # https://code.google.com/p/pymat2/wiki/WindowsTips
+  #- ps: (Get-Content "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat) | ForEach-Object { $_ -replace "vcvarsamd64.bat", "vcvars64.bat" } | Set-Content "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat
+  # - '%CMD_IN_ENV% echo "conv env"'
+  # - ps: 'ls "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin"'
+  # - if "%platform%" == "x86" call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat"
+  #- if "%platform%" == "x64" echo f | xcopy /f /y "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat" "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\amd64\vcvarsamd64.bat"
+  # - if "%platform%" == "x64" call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" amd64
+  # - if "%platform%" == "x64" set WIN64_ARG="WIN64=YES"
+
+
+  - ps: mkdir C:\build | out-null
+  - ps: mkdir C:\gdal | out-null
+  
+  - curl http://download.gisinternals.com/sdk/downloads/release-1600-x64-gdal-1-11-4-mapserver-6-4-3.zip --output gdalbin.zip
+  - 7z x gdalbin.zip -oC:\gdal
+  - curl http://download.gisinternals.com/sdk/downloads/release-1600-x64-gdal-1-11-4-mapserver-6-4-3-libs.zip --output gdallibs.zip  
+  - 7z x gdallibs.zip -oC:\gdal
+  - "SET PATH=C:\\gdal;C:\\gdal\\bin;C:\\gdal\\data;C:\\gdal\\bin\\gdal\\apps;%PATH%"
+  - "SET GDAL_DATA=C:\\gdal\\bin\\gdal-data"
+
+  - ECHO "Filesystem C:/GDAL:"
+  - ps: "ls \"C:/GDAL\""
+  
+  
+  - cd C:\projects\fiona
+  # Upgrade to the latest version of pip to avoid it displaying warnings
+  # about it being out of date.
+  # - "python -m pip install --disable-pip-version-check --user --upgrade pip"
+  
+  - pip --version
+ 
+  # Install the build dependencies of the project. If some dependencies contain
+  # compiled extensions and are not provided as pre-built wheel packages,
+  # pip will build them from source using the MSVC compiler matching the
+  # target Python version and architecture
+  - "%CMD_IN_ENV% pip install -r requirements-dev.txt"
+  
+
+build_script:
+  # Build the compiled extension
+  - cmd: echo %PATH%
+
+  - cmd: echo %PYTHONPATH%
+
+  - "%CMD_IN_ENV% python setup.py build_ext -IC:\\gdal\\include -lgdal_i -LC:\\gdal\\lib install --gdalversion 1.11.4"
+
+
+test_script:
+  # Run the project tests
+  - cmd: SET
+
+  - "%CMD_IN_ENV% nosetests --exclude test_filter_vsi --exclude test_geopackage"  
diff --git a/appveyor/install.ps1 b/appveyor/install.ps1
new file mode 100644
index 0000000..160ba55
--- /dev/null
+++ b/appveyor/install.ps1
@@ -0,0 +1,229 @@
+# Sample script to install Python and pip under Windows
+# Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer
+# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
+
+$MINICONDA_URL = "http://repo.continuum.io/miniconda/"
+$BASE_URL = "https://www.python.org/ftp/python/"
+$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
+$GET_PIP_PATH = "C:\get-pip.py"
+
+$PYTHON_PRERELEASE_REGEX = @"
+(?x)
+(?<major>\d+)
+\.
+(?<minor>\d+)
+\.
+(?<micro>\d+)
+(?<prerelease>[a-z]{1,2}\d+)
+"@
+
+
+function Download ($filename, $url) {
+    $webclient = New-Object System.Net.WebClient
+
+    $basedir = $pwd.Path + "\"
+    $filepath = $basedir + $filename
+    if (Test-Path $filename) {
+        Write-Host "Reusing" $filepath
+        return $filepath
+    }
+
+    # Download and retry up to 3 times in case of network transient errors.
+    Write-Host "Downloading" $filename "from" $url
+    $retry_attempts = 2
+    for ($i = 0; $i -lt $retry_attempts; $i++) {
+        try {
+            $webclient.DownloadFile($url, $filepath)
+            break
+        }
+        Catch [Exception]{
+            Start-Sleep 1
+        }
+    }
+    if (Test-Path $filepath) {
+        Write-Host "File saved at" $filepath
+    } else {
+        # Retry once to get the error message if any at the last try
+        $webclient.DownloadFile($url, $filepath)
+    }
+    return $filepath
+}
+
+
+function ParsePythonVersion ($python_version) {
+    if ($python_version -match $PYTHON_PRERELEASE_REGEX) {
+        return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro,
+                $matches.prerelease)
+    }
+    $version_obj = [version]$python_version
+    return ($version_obj.major, $version_obj.minor, $version_obj.build, "")
+}
+
+
+function DownloadPython ($python_version, $platform_suffix) {
+    $major, $minor, $micro, $prerelease = ParsePythonVersion $python_version
+
+    if (($major -le 2 -and $micro -eq 0) `
+        -or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) `
+        ) {
+        $dir = "$major.$minor"
+        $python_version = "$major.$minor$prerelease"
+    } else {
+        $dir = "$major.$minor.$micro"
+    }
+
+    if ($prerelease) {
+        if (($major -le 2) `
+            -or ($major -eq 3 -and $minor -eq 1) `
+            -or ($major -eq 3 -and $minor -eq 2) `
+            -or ($major -eq 3 -and $minor -eq 3) `
+            ) {
+            $dir = "$dir/prev"
+        }
+    }
+
+    if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) {
+        $ext = "msi"
+        if ($platform_suffix) {
+            $platform_suffix = ".$platform_suffix"
+        }
+    } else {
+        $ext = "exe"
+        if ($platform_suffix) {
+            $platform_suffix = "-$platform_suffix"
+        }
+    }
+
+    $filename = "python-$python_version$platform_suffix.$ext"
+    $url = "$BASE_URL$dir/$filename"
+    $filepath = Download $filename $url
+    return $filepath
+}
+
+
+function InstallPython ($python_version, $architecture, $python_home) {
+    Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home
+    if (Test-Path $python_home) {
+        Write-Host $python_home "already exists, skipping."
+        return $false
+    }
+    if ($architecture -eq "32") {
+        $platform_suffix = ""
+    } else {
+        $platform_suffix = "amd64"
+    }
+    $installer_path = DownloadPython $python_version $platform_suffix
+    $installer_ext = [System.IO.Path]::GetExtension($installer_path)
+    Write-Host "Installing $installer_path to $python_home"
+    $install_log = $python_home + ".log"
+    if ($installer_ext -eq '.msi') {
+        InstallPythonMSI $installer_path $python_home $install_log
+    } else {
+        InstallPythonEXE $installer_path $python_home $install_log
+    }
+    if (Test-Path $python_home) {
+        Write-Host "Python $python_version ($architecture) installation complete"
+    } else {
+        Write-Host "Failed to install Python in $python_home"
+        Get-Content -Path $install_log
+        Exit 1
+    }
+}
+
+
+function InstallPythonEXE ($exepath, $python_home, $install_log) {
+    $install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home"
+    RunCommand $exepath $install_args
+}
+
+
+function InstallPythonMSI ($msipath, $python_home, $install_log) {
+    $install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home"
+    $uninstall_args = "/qn /x $msipath"
+    RunCommand "msiexec.exe" $install_args
+    if (-not(Test-Path $python_home)) {
+        Write-Host "Python seems to be installed else-where, reinstalling."
+        RunCommand "msiexec.exe" $uninstall_args
+        RunCommand "msiexec.exe" $install_args
+    }
+}
+
+function RunCommand ($command, $command_args) {
+    Write-Host $command $command_args
+    Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru
+}
+
+
+function InstallPip ($python_home) {
+    $pip_path = $python_home + "\Scripts\pip.exe"
+    $python_path = $python_home + "\python.exe"
+    if (-not(Test-Path $pip_path)) {
+        Write-Host "Installing pip..."
+        $webclient = New-Object System.Net.WebClient
+        $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH)
+        Write-Host "Executing:" $python_path $GET_PIP_PATH
+        & $python_path $GET_PIP_PATH
+    } else {
+        Write-Host "pip already installed."
+    }
+}
+
+
+function DownloadMiniconda ($python_version, $platform_suffix) {
+    if ($python_version -eq "3.4") {
+        $filename = "Miniconda3-3.5.5-Windows-" + $platform_suffix + ".exe"
+    } else {
+        $filename = "Miniconda-3.5.5-Windows-" + $platform_suffix + ".exe"
+    }
+    $url = $MINICONDA_URL + $filename
+    $filepath = Download $filename $url
+    return $filepath
+}
+
+
+function InstallMiniconda ($python_version, $architecture, $python_home) {
+    Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home
+    if (Test-Path $python_home) {
+        Write-Host $python_home "already exists, skipping."
+        return $false
+    }
+    if ($architecture -eq "32") {
+        $platform_suffix = "x86"
+    } else {
+        $platform_suffix = "x86_64"
+    }
+    $filepath = DownloadMiniconda $python_version $platform_suffix
+    Write-Host "Installing" $filepath "to" $python_home
+    $install_log = $python_home + ".log"
+    $args = "/S /D=$python_home"
+    Write-Host $filepath $args
+    Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru
+    if (Test-Path $python_home) {
+        Write-Host "Python $python_version ($architecture) installation complete"
+    } else {
+        Write-Host "Failed to install Python in $python_home"
+        Get-Content -Path $install_log
+        Exit 1
+    }
+}
+
+
+function InstallMinicondaPip ($python_home) {
+    $pip_path = $python_home + "\Scripts\pip.exe"
+    $conda_path = $python_home + "\Scripts\conda.exe"
+    if (-not(Test-Path $pip_path)) {
+        Write-Host "Installing pip..."
+        $args = "install --yes pip"
+        Write-Host $conda_path $args
+        Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru
+    } else {
+        Write-Host "pip already installed."
+    }
+}
+
+function main () {
+    InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON
+    InstallPip $env:PYTHON
+}
+
+main
diff --git a/appveyor/run_with_env.cmd b/appveyor/run_with_env.cmd
new file mode 100644
index 0000000..5da547c
--- /dev/null
+++ b/appveyor/run_with_env.cmd
@@ -0,0 +1,88 @@
+:: To build extensions for 64 bit Python 3, we need to configure environment
+:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
+::
+:: To build extensions for 64 bit Python 2, we need to configure environment
+:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
+::
+:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific
+:: environment configurations.
+::
+:: Note: this script needs to be run with the /E:ON and /V:ON flags for the
+:: cmd interpreter, at least for (SDK v7.0)
+::
+:: More details at:
+:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
+:: http://stackoverflow.com/a/13751649/163740
+::
+:: Author: Olivier Grisel
+:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
+::
+:: Notes about batch files for Python people:
+::
+:: Quotes in values are literally part of the values:
+::      SET FOO="bar"
+:: FOO is now five characters long: " b a r "
+:: If you don't want quotes, don't include them on the right-hand side.
+::
+:: The CALL lines at the end of this file look redundant, but if you move them
+:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y
+:: case, I don't know why.
+ at ECHO OFF
+
+SET COMMAND_TO_RUN=%*
+SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
+SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf
+
+:: Extract the major and minor versions, and allow for the minor version to be
+:: more than 9.  This requires the version number to have two dots in it.
+SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1%
+IF "%PYTHON_VERSION:~3,1%" == "." (
+    SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1%
+) ELSE (
+    SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2%
+)
+
+:: Based on the Python version, determine what SDK version to use, and whether
+:: to set the SDK for 64-bit.
+IF %MAJOR_PYTHON_VERSION% == 2 (
+    SET WINDOWS_SDK_VERSION="v7.0"
+    SET SET_SDK_64=Y
+) ELSE (
+    IF %MAJOR_PYTHON_VERSION% == 3 (
+        SET WINDOWS_SDK_VERSION="v7.1"
+        IF %MINOR_PYTHON_VERSION% LEQ 4 (
+            SET SET_SDK_64=Y
+        ) ELSE (
+            SET SET_SDK_64=N
+            IF EXIST "%WIN_WDK%" (
+                :: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/
+                REN "%WIN_WDK%" 0wdf
+            )
+        )
+    ) ELSE (
+        ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%"
+        EXIT 1
+    )
+)
+
+IF %PYTHON_ARCH% == 64 (
+    IF %SET_SDK_64% == Y (
+        ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture
+        SET DISTUTILS_USE_SDK=1
+        SET MSSdk=1
+        "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
+        "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
+        ECHO Executing: %COMMAND_TO_RUN%
+        call %COMMAND_TO_RUN% || EXIT 1
+    ) ELSE (
+        ECHO Using default MSVC build environment for 64 bit architecture
+        ECHO Executing: %COMMAND_TO_RUN%
+        call %COMMAND_TO_RUN% || EXIT 1
+    )
+) ELSE (
+    ECHO Using default MSVC build environment for 32 bit architecture
+    ECHO Executing: %COMMAND_TO_RUN%
+    call %COMMAND_TO_RUN% || EXIT 1
+)
diff --git a/fiona/__init__.py b/fiona/__init__.py
index 5048a65..e17a2d6 100644
--- a/fiona/__init__.py
+++ b/fiona/__init__.py
@@ -81,7 +81,7 @@ import uuid
 
 
 __all__ = ['bounds', 'listlayers', 'open', 'prop_type', 'prop_width']
-__version__ = "1.7b1"
+__version__ = "1.7.0"
 __gdal_version__ = get_gdal_release_name().decode('utf-8')
 
 log = logging.getLogger('Fiona')
diff --git a/fiona/_cpl.pxd b/fiona/_cpl.pxd
index 6e43893..609ee41 100644
--- a/fiona/_cpl.pxd
+++ b/fiona/_cpl.pxd
@@ -1,13 +1,11 @@
+# Cross-platform API functions.
+
 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
diff --git a/fiona/_crs.pxd b/fiona/_crs.pxd
index 999d08d..7329cb0 100644
--- a/fiona/_crs.pxd
+++ b/fiona/_crs.pxd
@@ -1,3 +1,5 @@
+# Coordinate system and transform API functions.
+
 cdef extern from "ogr_srs_api.h":
     void    OSRCleanup ()
     void *  OSRClone (void *srs)
diff --git a/fiona/_crs.pyx b/fiona/_crs.pyx
index b4da1cb..fc3dcd1 100644
--- a/fiona/_crs.pyx
+++ b/fiona/_crs.pyx
@@ -7,7 +7,7 @@ import logging
 
 from six import string_types
 
-from fiona cimport _cpl, _crs
+cimport _cpl
 from fiona.errors import CRSError
 
 
@@ -20,7 +20,7 @@ def crs_to_wkt(crs):
     cdef void *cogr_srs = NULL
     cdef char *proj_c = NULL
 
-    cogr_srs = _crs.OSRNewSpatialReference(NULL)
+    cogr_srs = OSRNewSpatialReference(NULL)
     if cogr_srs == NULL:
         raise CRSError("NULL spatial reference")
 
@@ -28,7 +28,7 @@ def crs_to_wkt(crs):
     if isinstance(crs, string_types):
         proj_b = crs.encode('utf-8')
         proj_c = proj_b
-        _crs.OSRSetFromUserInput(cogr_srs, proj_c)
+        OSRSetFromUserInput(cogr_srs, proj_c)
     elif isinstance(crs, dict):
         # EPSG is a special case.
         init = crs.get('init')
@@ -37,7 +37,7 @@ def crs_to_wkt(crs):
             auth, val = init.split(':')
             if auth.upper() == 'EPSG':
                 logger.debug("Setting EPSG: %s", val)
-                _crs.OSRImportFromEPSG(cogr_srs, int(val))
+                OSRImportFromEPSG(cogr_srs, int(val))
         else:
             params = []
             crs['wktext'] = True
@@ -50,14 +50,14 @@ def crs_to_wkt(crs):
             logger.debug("PROJ.4 to be imported: %r", proj)
             proj_b = proj.encode('utf-8')
             proj_c = proj_b
-            _crs.OSRImportFromProj4(cogr_srs, proj_c)
+            OSRImportFromProj4(cogr_srs, proj_c)
     else:
         raise ValueError("Invalid CRS")
 
     # Fixup, export to WKT, and set the GDAL dataset's projection.
-    _crs.OSRFixup(cogr_srs)
+    OSRFixup(cogr_srs)
 
-    _crs.OSRExportToWkt(cogr_srs, &proj_c)
+    OSRExportToWkt(cogr_srs, &proj_c)
 
     if proj_c == NULL:
         raise CRSError("Null projection")
diff --git a/fiona/_csl.pxd b/fiona/_csl.pxd
new file mode 100644
index 0000000..fe1a4eb
--- /dev/null
+++ b/fiona/_csl.pxd
@@ -0,0 +1,5 @@
+# String API functions.
+
+cdef extern from "cpl_string.h":
+    char ** CSLSetNameValue (char **list, char *name, char *value)
+    void    CSLDestroy (char **list)
diff --git a/fiona/_geometry.pxd b/fiona/_geometry.pxd
index 2bf2cc1..9f3eb6e 100644
--- a/fiona/_geometry.pxd
+++ b/fiona/_geometry.pxd
@@ -1,3 +1,36 @@
+# Geometry API functions.
+
+ctypedef int OGRErr
+
+
+ctypedef struct OGREnvelope:
+    double MinX
+    double MaxX
+    double MinY
+    double MaxY
+
+
+cdef extern from "ogr_api.h":
+    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)
+
 
 cdef class GeomBuilder:
     cdef void *geom
diff --git a/fiona/_geometry.pyx b/fiona/_geometry.pyx
index 5014c40..6d57895 100644
--- a/fiona/_geometry.pyx
+++ b/fiona/_geometry.pyx
@@ -2,15 +2,13 @@
 
 import logging
 
-from fiona cimport ograpi
 
-
-log = logging.getLogger("Fiona")
 class NullHandler(logging.Handler):
     def emit(self, record):
         pass
-log.addHandler(NullHandler())
 
+log = logging.getLogger("Fiona")
+log.addHandler(NullHandler())
 
 # Mapping of OGR integer geometry types to GeoJSON type names.
 GEOMETRY_TYPES = {
@@ -41,16 +39,16 @@ cdef void * _createOgrGeomFromWKB(object wkb) except NULL:
     """Make an OGR geometry from a WKB string"""
     wkbtype = bytearray(wkb)[1]
     cdef unsigned char *buffer = wkb
-    cdef void *cogr_geometry = ograpi.OGR_G_CreateGeometry(wkbtype)
+    cdef void *cogr_geometry = OGR_G_CreateGeometry(wkbtype)
     if cogr_geometry is not NULL:
-        ograpi.OGR_G_ImportFromWkb(cogr_geometry, buffer, len(wkb))
+        OGR_G_ImportFromWkb(cogr_geometry, buffer, len(wkb))
     return cogr_geometry
 
 
 cdef _deleteOgrGeom(void *cogr_geometry):
     """Delete an OGR geometry"""
     if cogr_geometry is not NULL:
-        ograpi.OGR_G_DestroyGeometry(cogr_geometry)
+        OGR_G_DestroyGeometry(cogr_geometry)
     cogr_geometry = NULL
 
 
@@ -62,12 +60,12 @@ cdef class GeomBuilder:
         cdef int i
         if geom == NULL:
             raise ValueError("Null geom")
-        npoints = ograpi.OGR_G_GetPointCount(geom)
+        npoints = OGR_G_GetPointCount(geom)
         coords = []
         for i in range(npoints):
-            values = [ograpi.OGR_G_GetX(geom, i), ograpi.OGR_G_GetY(geom, i)]
+            values = [OGR_G_GetX(geom, i), OGR_G_GetY(geom, i)]
             if self.ndims > 2:
-                values.append(ograpi.OGR_G_GetZ(geom, i))
+                values.append(OGR_G_GetZ(geom, i))
             coords.append(tuple(values))
         return coords
     
@@ -86,8 +84,8 @@ cdef class GeomBuilder:
         if geom == NULL:
             raise ValueError("Null geom")
         parts = []
-        for j in range(ograpi.OGR_G_GetGeometryCount(geom)):
-            part = ograpi.OGR_G_GetGeometryRef(geom, j)
+        for j in range(OGR_G_GetGeometryCount(geom)):
+            part = OGR_G_GetGeometryRef(geom, j)
             parts.append(GeomBuilder().build(part))
         return parts
     
@@ -116,10 +114,10 @@ cdef class GeomBuilder:
         if geom == NULL:
             raise ValueError("Null geom")
         
-        cdef unsigned int etype = ograpi.OGR_G_GetGeometryType(geom)
+        cdef unsigned int etype = OGR_G_GetGeometryType(geom)
         self.code = etype
         self.geomtypename = GEOMETRY_TYPES[self.code & (~0x80000000)]
-        self.ndims = ograpi.OGR_G_GetCoordinateDimension(geom)
+        self.ndims = OGR_G_GetCoordinateDimension(geom)
         self.geom = geom
         return getattr(self, '_build' + self.geomtypename)()
     
@@ -136,7 +134,7 @@ cdef class OGRGeomBuilder:
     """Builds OGR geometries from Fiona geometries.
     """
     cdef void * _createOgrGeometry(self, int geom_type) except NULL:
-        cdef void *cogr_geometry = ograpi.OGR_G_CreateGeometry(geom_type)
+        cdef void *cogr_geometry = OGR_G_CreateGeometry(geom_type)
         if cogr_geometry == NULL:
             raise Exception("Could not create OGR Geometry of type: %i" % geom_type)
         return cogr_geometry
@@ -144,10 +142,10 @@ cdef class OGRGeomBuilder:
     cdef _addPointToGeometry(self, void *cogr_geometry, object coordinate):
         if len(coordinate) == 2:
             x, y = coordinate
-            ograpi.OGR_G_AddPoint_2D(cogr_geometry, x, y)
+            OGR_G_AddPoint_2D(cogr_geometry, x, y)
         else:
             x, y, z = coordinate[:3]
-            ograpi.OGR_G_AddPoint(cogr_geometry, x, y, z)
+            OGR_G_AddPoint(cogr_geometry, x, y, z)
 
     cdef void * _buildPoint(self, object coordinates) except NULL:
         cdef void *cogr_geometry = self._createOgrGeometry(GEOJSON2OGR_GEOMETRY_TYPES['Point'])
@@ -167,7 +165,7 @@ cdef class OGRGeomBuilder:
             log.debug("Adding point %s", coordinate)
             self._addPointToGeometry(cogr_geometry, coordinate)
         log.debug("Closing ring")
-        ograpi.OGR_G_CloseRings(cogr_geometry)
+        OGR_G_CloseRings(cogr_geometry)
         return cogr_geometry
     
     cdef void * _buildPolygon(self, object coordinates) except NULL:
@@ -177,7 +175,7 @@ cdef class OGRGeomBuilder:
             log.debug("Adding ring %s", ring)
             cogr_ring = self._buildLinearRing(ring)
             log.debug("Built ring")
-            ograpi.OGR_G_AddGeometryDirectly(cogr_geometry, cogr_ring)
+            OGR_G_AddGeometryDirectly(cogr_geometry, cogr_ring)
             log.debug("Added ring %s", ring)
         return cogr_geometry
 
@@ -187,7 +185,7 @@ cdef class OGRGeomBuilder:
         for coordinate in coordinates:
             log.debug("Adding point %s", coordinate)
             cogr_part = self._buildPoint(coordinate)
-            ograpi.OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
+            OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
             log.debug("Added point %s", coordinate)
         return cogr_geometry
 
@@ -198,7 +196,7 @@ cdef class OGRGeomBuilder:
             log.debug("Adding line %s", line)
             cogr_part = self._buildLineString(line)
             log.debug("Built line")
-            ograpi.OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
+            OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
             log.debug("Added line %s", line)
         return cogr_geometry
 
@@ -209,7 +207,7 @@ cdef class OGRGeomBuilder:
             log.debug("Adding polygon %s", part)
             cogr_part = self._buildPolygon(part)
             log.debug("Built polygon")
-            ograpi.OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
+            OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
             log.debug("Added polygon %s", part)
         return cogr_geometry
 
@@ -220,7 +218,7 @@ cdef class OGRGeomBuilder:
             log.debug("Adding part %s", part)
             cogr_part = OGRGeomBuilder().build(part)
             log.debug("Built part")
-            ograpi.OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
+            OGR_G_AddGeometryDirectly(cogr_geometry, cogr_part)
             log.debug("Added part %s", part)
         return cogr_geometry
 
diff --git a/fiona/_transform.pyx b/fiona/_transform.pyx
index 3d5dd69..6c5460b 100644
--- a/fiona/_transform.pyx
+++ b/fiona/_transform.pyx
@@ -4,7 +4,10 @@
 
 import logging
 
-from fiona cimport ograpi, _geometry
+cimport _cpl
+cimport _crs
+cimport _csl
+cimport _geometry
 
 
 cdef extern from "ogr_geometry.h" nogil:
@@ -29,10 +32,10 @@ class NullHandler(logging.Handler):
 log.addHandler(NullHandler())
 
 
-cdef void *_osr_from_crs(object crs):
+cdef void *_crs_from_crs(object crs):
     cdef char *proj_c = NULL
     cdef void *osr = NULL
-    osr = ograpi.OSRNewSpatialReference(NULL)
+    osr = _crs.OSRNewSpatialReference(NULL)
     if osr == NULL:
         raise ValueError("NULL spatial reference")
     params = []
@@ -43,7 +46,7 @@ cdef void *_osr_from_crs(object crs):
         if init:
             auth, val = init.split(':')
             if auth.upper() == 'EPSG':
-                ograpi.OSRImportFromEPSG(osr, int(val))
+                _crs.OSRImportFromEPSG(osr, int(val))
         else:
             crs['wktext'] = True
             for k, v in crs.items():
@@ -55,12 +58,12 @@ cdef void *_osr_from_crs(object crs):
             log.debug("PROJ.4 to be imported: %r", proj)
             proj_b = proj.encode('utf-8')
             proj_c = proj_b
-            ograpi.OSRImportFromProj4(osr, proj_c)
+            _crs.OSRImportFromProj4(osr, proj_c)
     # Fall back for CRS strings like "EPSG:3857."
     else:
         proj_b = crs.encode('utf-8')
         proj_c = proj_b
-        ograpi.OSRSetFromUserInput(osr, proj_c)
+        _crs.OSRSetFromUserInput(osr, proj_c)
     return osr
 
 
@@ -73,18 +76,18 @@ def _transform(src_crs, dst_crs, xs, ys):
 
     assert len(xs) == len(ys)
 
-    src = _osr_from_crs(src_crs)
-    dst = _osr_from_crs(dst_crs)
+    src = _crs_from_crs(src_crs)
+    dst = _crs_from_crs(dst_crs)
 
     n = len(xs)
-    x = <double *>ograpi.CPLMalloc(n*sizeof(double))
-    y = <double *>ograpi.CPLMalloc(n*sizeof(double))
+    x = <double *>_cpl.CPLMalloc(n*sizeof(double))
+    y = <double *>_cpl.CPLMalloc(n*sizeof(double))
     for i in range(n):
         x[i] = xs[i]
         y[i] = ys[i]
 
-    transform = ograpi.OCTNewCoordinateTransformation(src, dst)
-    res = ograpi.OCTTransform(transform, n, x, y, NULL)
+    transform = _crs.OCTNewCoordinateTransformation(src, dst)
+    res = _crs.OCTTransform(transform, n, x, y, NULL)
 
     res_xs = [0]*n
     res_ys = [0]*n
@@ -93,11 +96,11 @@ def _transform(src_crs, dst_crs, xs, ys):
         res_xs[i] = x[i]
         res_ys[i] = y[i]
 
-    ograpi.CPLFree(x)
-    ograpi.CPLFree(y)
-    ograpi.OCTDestroyCoordinateTransformation(transform)
-    ograpi.OSRDestroySpatialReference(src)
-    ograpi.OSRDestroySpatialReference(dst)
+    _cpl.CPLFree(x)
+    _cpl.CPLFree(y)
+    _crs.OCTDestroyCoordinateTransformation(transform)
+    _crs.OSRDestroySpatialReference(src)
+    _crs.OSRDestroySpatialReference(dst)
     return res_xs, res_ys
 
 
@@ -117,16 +120,16 @@ def _transform_geom(
     cdef int i
 
     if src_crs and dst_crs:
-        src = _osr_from_crs(src_crs)
-        dst = _osr_from_crs(dst_crs)
-        transform = ograpi.OCTNewCoordinateTransformation(src, dst)
+        src = _crs_from_crs(src_crs)
+        dst = _crs_from_crs(dst_crs)
+        transform = _crs.OCTNewCoordinateTransformation(src, dst)
 
         # Transform options.
-        options = ograpi.CSLSetNameValue(
+        options = _csl.CSLSetNameValue(
                     options, "DATELINEOFFSET", 
                     str(antimeridian_offset).encode('utf-8'))
         if antimeridian_cutting:
-            options = ograpi.CSLSetNameValue(options, "WRAPDATELINE", "YES")
+            options = _csl.CSLSetNameValue(options, "WRAPDATELINE", "YES")
 
         factory = new OGRGeometryFactory()
         src_ogr_geom = _geometry.OGRGeomBuilder().build(geom)
@@ -136,13 +139,13 @@ def _transform_geom(
                         options)
         g = _geometry.GeomBuilder().build(dst_ogr_geom)
 
-        ograpi.OGR_G_DestroyGeometry(dst_ogr_geom)
-        ograpi.OGR_G_DestroyGeometry(src_ogr_geom)
-        ograpi.OCTDestroyCoordinateTransformation(transform)
+        _geometry.OGR_G_DestroyGeometry(dst_ogr_geom)
+        _geometry.OGR_G_DestroyGeometry(src_ogr_geom)
+        _crs.OCTDestroyCoordinateTransformation(transform)
         if options != NULL:
-            ograpi.CSLDestroy(options)
-        ograpi.OSRDestroySpatialReference(src)
-        ograpi.OSRDestroySpatialReference(dst)
+            _csl.CSLDestroy(options)
+        _crs.OSRDestroySpatialReference(src)
+        _crs.OSRDestroySpatialReference(dst)
     else:
         g = geom
     if precision >= 0:
diff --git a/fiona/fio/cat.py b/fiona/fio/cat.py
index 9b97199..4562d16 100644
--- a/fiona/fio/cat.py
+++ b/fiona/fio/cat.py
@@ -19,6 +19,11 @@ warnings.simplefilter('default')
 # Cat command
 @click.command(short_help="Concatenate and print the features of datasets")
 @cligj.files_in_arg
+ at click.option('--layer', default=None, multiple=True,
+              callback=options.cb_multilayer,
+              help="Input layer(s), specified as 'fileindex:layer` "
+                   "For example, '1:foo,2:bar' will concatenate layer foo "
+                   "from file 1 and layer bar from file 2")
 @cligj.precision_opt
 @cligj.indent_opt
 @cligj.compact_opt
@@ -30,9 +35,16 @@ warnings.simplefilter('default')
               help="filter for features intersecting a bounding box")
 @click.pass_context
 def cat(ctx, files, precision, indent, compact, ignore_errors, dst_crs,
-        use_rs, bbox):
-    """Concatenate and print the features of input datasets as a
-    sequence of GeoJSON features."""
+        use_rs, bbox, layer):
+
+    """
+    Concatenate and print the features of input datasets as a sequence of
+    GeoJSON features.
+
+    When working with a multi-layer dataset the first layer is used by default.
+    Use the '--layer' option to select a different layer.
+    """
+
     verbosity = (ctx.obj and ctx.obj['verbosity']) or 2
     logger = logging.getLogger('fio')
 
@@ -42,27 +54,35 @@ def cat(ctx, files, precision, indent, compact, ignore_errors, dst_crs,
     if compact:
         dump_kwds['separators'] = (',', ':')
     item_sep = compact and ',' or ', '
-
+    # Validate file idexes provided in --layer option
+    # (can't pass the files to option callback)
+    if layer:
+        options.validate_multilayer_file_index(files, layer)
+    # first layer is the default
+    for i in range(1, len(files) + 1):
+        if str(i) not in layer.keys():
+            layer[str(i)] = [0]
     try:
         with fiona.drivers(CPL_DEBUG=verbosity > 2):
-            for path in files:
-                with fiona.open(path) as src:
-                    if bbox:
-                        try:
-                            bbox = tuple(map(float, bbox.split(',')))
-                        except ValueError:
-                            bbox = json.loads(bbox)
-                    for i, feat in src.items(bbox=bbox):
-                        if dst_crs or precision > 0:
-                            g = transform_geom(
-                                    src.crs, dst_crs, feat['geometry'],
-                                    antimeridian_cutting=True,
-                                    precision=precision)
-                            feat['geometry'] = g
-                            feat['bbox'] = fiona.bounds(g)
-                        if use_rs:
-                            click.echo(u'\u001e', nl=False)
-                        click.echo(json.dumps(feat, **dump_kwds))
+            for i, path in enumerate(files, 1):
+                for lyr in layer[str(i)]:
+                    with fiona.open(path, layer=lyr) as src:
+                        if bbox:
+                            try:
+                                bbox = tuple(map(float, bbox.split(',')))
+                            except ValueError:
+                                bbox = json.loads(bbox)
+                        for i, feat in src.items(bbox=bbox):
+                            if dst_crs or precision > 0:
+                                g = transform_geom(
+                                        src.crs, dst_crs, feat['geometry'],
+                                        antimeridian_cutting=True,
+                                        precision=precision)
+                                feat['geometry'] = g
+                                feat['bbox'] = fiona.bounds(g)
+                            if use_rs:
+                                click.echo(u'\u001e', nl=False)
+                            click.echo(json.dumps(feat, **dump_kwds))
 
     except Exception:
         logger.exception("Exception caught during processing")
diff --git a/fiona/fio/dump.py b/fiona/fio/dump.py
index 6968285..b7397a2 100644
--- a/fiona/fio/dump.py
+++ b/fiona/fio/dump.py
@@ -10,11 +10,16 @@ import cligj
 
 import fiona
 from fiona.fio import helpers
+from fiona.fio import options
 from fiona.transform import transform_geom
 
 
 @click.command(short_help="Dump a dataset to GeoJSON.")
 @click.argument('input', type=click.Path(), required=True)
+ at click.option('--layer', metavar="INDEX|NAME", callback=options.cb_layer,
+              help="Print information about a specific layer.  The first "
+                   "layer is used by default.  Layers use zero-based "
+                   "numbering when accessed by index.")
 @click.option('--encoding', help="Specify encoding of the input file.")
 @cligj.precision_opt
 @cligj.indent_opt
@@ -31,7 +36,7 @@ from fiona.transform import transform_geom
                    "context.")
 @click.pass_context
 def dump(ctx, input, encoding, precision, indent, compact, record_buffered,
-         ignore_errors, with_ld_context, add_ld_context_item):
+         ignore_errors, with_ld_context, add_ld_context_item, layer):
 
     """Dump a dataset either as a GeoJSON feature collection (the default)
     or a sequence of GeoJSON features."""
@@ -50,6 +55,8 @@ def dump(ctx, input, encoding, precision, indent, compact, record_buffered,
     open_kwds = {}
     if encoding:
         open_kwds['encoding'] = encoding
+    if layer:
+        open_kwds['layer'] = layer
 
     def transformer(crs, feat):
         tg = partial(transform_geom, crs, 'EPSG:4326',
diff --git a/fiona/fio/options.py b/fiona/fio/options.py
index 6a7a62b..d916227 100644
--- a/fiona/fio/options.py
+++ b/fiona/fio/options.py
@@ -1,6 +1,8 @@
 """Common commandline options for `fio`"""
 
 
+from collections import defaultdict
+
 import click
 
 
@@ -10,8 +12,34 @@ dst_crs_opt = click.option('--dst-crs', '--dst_crs', help="Destination CRS.")
 
 def cb_layer(ctx, param, value):
     """Let --layer be a name or index."""
-
     if value is None or not value.isdigit():
         return value
     else:
         return int(value)
+
+
+def cb_multilayer(ctx, param, value):
+    """
+    Transform layer options from strings ("1:a,1:b", "2:a,2:c,2:z") to
+    {
+    '1': ['a', 'b'],
+    '2': ['a', 'c', 'z']
+    }
+    """
+    out = defaultdict(list)
+    for raw in value:
+        for v in raw.split(','):
+            ds, name = v.split(':')
+            out[ds].append(name)
+    return out
+
+
+def validate_multilayer_file_index(files, layerdict):
+    """
+    Ensure file indexes provided in the --layer option are valid
+    """
+    for key in layerdict.keys():
+        click.echo(key)
+        if key not in [str(k) for k in range(1, len(files) + 1)]:
+            layer = key+":"+layerdict[key][0]
+            raise click.BadParameter("Layer {} does not exist".format(layer))
diff --git a/fiona/ograpi1.pxd b/fiona/ogrext1.pxd
similarity index 100%
rename from fiona/ograpi1.pxd
rename to fiona/ogrext1.pxd
diff --git a/fiona/ogrext1.pyx b/fiona/ogrext1.pyx
index 56ae391..e9b14a1 100644
--- a/fiona/ogrext1.pyx
+++ b/fiona/ogrext1.pyx
@@ -12,8 +12,8 @@ import uuid
 
 from six import integer_types, string_types, text_type
 
-from fiona cimport ograpi
-from fiona._geometry cimport GeomBuilder, OGRGeomBuilder
+cimport ogrext1
+from _geometry cimport GeomBuilder, OGRGeomBuilder
 from fiona._err import cpl_errs
 from fiona._geometry import GEOMETRY_TYPES
 from fiona.errors import (
@@ -123,11 +123,11 @@ def calc_gdal_version_num(maj, min, rev):
 
 def get_gdal_version_num():
     """Return current internal version number of gdal"""
-    return int(ograpi.GDALVersionInfo("VERSION_NUM"))
+    return int(ogrext1.GDALVersionInfo("VERSION_NUM"))
 
 def get_gdal_release_name():
     """Return release name of gdal"""
-    return ograpi.GDALVersionInfo("RELEASE_NAME")
+    return ogrext1.GDALVersionInfo("RELEASE_NAME")
 
 
 # Feature extension classes and functions follow.
@@ -153,35 +153,35 @@ cdef class FeatureBuilder:
         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)
+        for i in range(ogrext1.OGR_F_GetFieldCount(feature)):
+            fdefn = ogrext1.OGR_F_GetFieldDefnRef(feature, i)
             if fdefn == NULL:
                 raise ValueError("Null feature definition")
-            key_c = ograpi.OGR_Fld_GetNameRef(fdefn)
+            key_c = ogrext1.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)]
+            fieldtypename = FIELD_TYPES[ogrext1.OGR_Fld_GetType(fdefn)]
             if not fieldtypename:
                 log.warn(
                     "Skipping field %s: invalid type %s", 
                     key,
-                    ograpi.OGR_Fld_GetType(fdefn))
+                    ogrext1.OGR_Fld_GetType(fdefn))
                 continue
 
             # TODO: other types
             fieldtype = FIELD_TYPES_MAP[fieldtypename]
-            if not ograpi.OGR_F_IsFieldSet(feature, i):
+            if not ogrext1.OGR_F_IsFieldSet(feature, i):
                 props[key] = None
             elif fieldtype is int:
-                props[key] = ograpi.OGR_F_GetFieldAsInteger(feature, i)
+                props[key] = ogrext1.OGR_F_GetFieldAsInteger(feature, i)
             elif fieldtype is float:
-                props[key] = ograpi.OGR_F_GetFieldAsDouble(feature, i)
+                props[key] = ogrext1.OGR_F_GetFieldAsDouble(feature, i)
 
             elif fieldtype is text_type:
                 try:
-                    val = ograpi.OGR_F_GetFieldAsString(feature, i)
+                    val = ogrext1.OGR_F_GetFieldAsString(feature, i)
                     val = val.decode(encoding)
                 except UnicodeError:
                     log.error("Failed to decode property '%s' value '%s'",
@@ -200,7 +200,7 @@ cdef class FeatureBuilder:
                 props[key] = val
 
             elif fieldtype in (FionaDateType, FionaTimeType, FionaDateTimeType):
-                retval = ograpi.OGR_F_GetFieldAsDateTime(
+                retval = ogrext1.OGR_F_GetFieldAsDateTime(
                     feature, i, &y, &m, &d, &hh, &mm, &ss, &tz)
                 if fieldtype is FionaDateType:
                     props[key] = datetime.date(y, m, d).isoformat()
@@ -213,14 +213,14 @@ cdef class FeatureBuilder:
                 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)
+        cdef void *cogr_geometry = ogrext1.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)),
+            'id': str(ogrext1.OGR_F_GetFID(feature)),
             'geometry': geom,
             'properties': props }
 
@@ -241,17 +241,17 @@ cdef class OGRFeatureBuilder:
         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)
+        cdef void *cogr_featuredefn = ogrext1.OGR_L_GetLayerDefn(cogr_layer)
         if cogr_featuredefn == NULL:
             raise ValueError("Null feature definition")
-        cdef void *cogr_feature = ograpi.OGR_F_Create(cogr_featuredefn)
+        cdef void *cogr_feature = ogrext1.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)
+        ogrext1.OGR_F_SetGeometryDirectly(cogr_feature, cogr_geometry)
         
         # OGR_F_SetFieldString takes UTF-8 encoded strings ('bytes' in 
         # Python 3).
@@ -272,7 +272,7 @@ cdef class OGRFeatureBuilder:
                 raise
 
             key_c = key_bytes
-            i = ograpi.OGR_F_GetFieldIndex(cogr_feature, key_c)
+            i = ogrext1.OGR_F_GetFieldIndex(cogr_feature, key_c)
             if i < 0:
                 continue
 
@@ -282,9 +282,9 @@ cdef class OGRFeatureBuilder:
 
             # Continue over the standard OGR types.
             if isinstance(value, integer_types):
-                ograpi.OGR_F_SetFieldInteger(cogr_feature, i, value)
+                ogrext1.OGR_F_SetFieldInteger(cogr_feature, i, value)
             elif isinstance(value, float):
-                ograpi.OGR_F_SetFieldDouble(cogr_feature, i, value)
+                ogrext1.OGR_F_SetFieldDouble(cogr_feature, i, value)
             elif (isinstance(value, string_types) 
             and schema_type in ['date', 'time', 'datetime']):
                 if schema_type == 'date':
@@ -293,23 +293,23 @@ cdef class OGRFeatureBuilder:
                     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(
+                ogrext1.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(
+                ogrext1.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(
+                ogrext1.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(
+                ogrext1.OGR_F_SetFieldDateTime(
                     cogr_feature, i, 0, 0, 0, hh, mm, ss, 0)
             elif isinstance(value, string_types):
                 # Catch, log, and re-raise string field value encoding errors.
@@ -320,7 +320,7 @@ cdef class OGRFeatureBuilder:
                               key, value)
                     raise
                 string_c = value_bytes
-                ograpi.OGR_F_SetFieldString(cogr_feature, i, string_c)
+                ogrext1.OGR_F_SetFieldString(cogr_feature, i, string_c)
             elif value is None:
                 pass # keep field unset/null
             else:
@@ -332,17 +332,17 @@ cdef class OGRFeatureBuilder:
 cdef _deleteOgrFeature(void *cogr_feature):
     """Delete an OGR feature"""
     if cogr_feature is not NULL:
-        ograpi.OGR_F_Destroy(cogr_feature)
+        ogrext1.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)
+    cdef void *cogr_geometry = ogrext1.OGR_F_GetGeometryRef(cogr_feature)
     if cogr_geometry == NULL:
         raise ValueError("Null geometry")
-    log.debug("Geometry: %s" % ograpi.OGR_G_ExportToJson(cogr_geometry))
+    log.debug("Geometry: %s" % ogrext1.OGR_G_ExportToJson(cogr_geometry))
     encoding = collection.encoding or 'utf-8'
     result = FeatureBuilder().build(
         cogr_feature,
@@ -364,7 +364,7 @@ cdef class Session:
     cdef object _encoding
     cdef object collection
 
-    def __cinit__(self):
+    def __init__(self):
         self.cogr_ds = NULL
         self.cogr_layer = NULL
         self._fileencoding = None
@@ -401,15 +401,15 @@ cdef class Session:
                     name_b = name.encode()
                     name_c = name_b
                     log.debug("Trying driver: %s", name)
-                    drv = ograpi.OGRGetDriverByName(name_c)
+                    drv = ogrext1.OGRGetDriverByName(name_c)
                     if drv != NULL:
-                        ds = ograpi.OGR_Dr_Open(drv, path_c, 0)
+                        ds = ogrext1.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)
+                self.cogr_ds = ogrext1.OGROpen(path_c, 0, NULL)
 
         if self.cogr_ds == NULL:
             raise FionaValueError(
@@ -420,12 +420,12 @@ cdef class Session:
         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_layer = ogrext1.OGR_DS_GetLayerByName(
                                 self.cogr_ds, name_c)
         elif isinstance(collection.name, int):
-            self.cogr_layer = ograpi.OGR_DS_GetLayer(
+            self.cogr_layer = ogrext1.OGR_DS_GetLayer(
                                 self.cogr_ds, collection.name)
-            name_c = ograpi.OGR_L_GetName(self.cogr_layer)
+            name_c = ogrext1.OGR_L_GetName(self.cogr_layer)
             name_b = name_c
             collection.name = name_b.decode('utf-8')
 
@@ -436,11 +436,11 @@ cdef class Session:
         
         userencoding = self.collection.encoding
         if userencoding:
-            ograpi.CPLSetThreadLocalConfigOption('SHAPE_ENCODING', '')
+            ogrext1.CPLSetThreadLocalConfigOption('SHAPE_ENCODING', '')
             self._fileencoding = userencoding.upper()
         else:
             self._fileencoding = (
-                ograpi.OGR_L_TestCapability(
+                ogrext1.OGR_L_TestCapability(
                     self.cogr_layer, OLC_STRINGSASUTF8) and
                 'utf-8') or (
                 self.get_driver() == "ESRI Shapefile" and
@@ -449,7 +449,7 @@ cdef class Session:
     def stop(self):
         self.cogr_layer = NULL
         if self.cogr_ds is not NULL:
-            ograpi.OGR_DS_Destroy(self.cogr_ds)
+            ogrext1.OGR_DS_Destroy(self.cogr_ds)
         self.cogr_ds = NULL
 
     def get_fileencoding(self):
@@ -459,7 +459,7 @@ cdef class Session:
         if not self._encoding:
             fileencoding = self.get_fileencoding()
             self._encoding = (
-                ograpi.OGR_L_TestCapability(
+                ogrext1.OGR_L_TestCapability(
                     self.cogr_layer, OLC_STRINGSASUTF8) and
                 'utf-8') or fileencoding
         return self._encoding
@@ -467,13 +467,13 @@ cdef class Session:
     def get_length(self):
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        return ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
+        return ogrext1.OGR_L_GetFeatureCount(self.cogr_layer, 0)
 
     def get_driver(self):
-        cdef void *cogr_driver = ograpi.OGR_DS_GetDriver(self.cogr_ds)
+        cdef void *cogr_driver = ogrext1.OGR_DS_GetDriver(self.cogr_ds)
         if cogr_driver == NULL:
             raise ValueError("Null driver")
-        cdef char *name = ograpi.OGR_Dr_GetName(cogr_driver)
+        cdef char *name = ogrext1.OGR_Dr_GetName(cogr_driver)
         driver_name = name
         return driver_name.decode()
  
@@ -488,52 +488,52 @@ cdef class Session:
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
 
-        cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(self.cogr_layer)
+        cogr_featuredefn = ogrext1.OGR_L_GetLayerDefn(self.cogr_layer)
         if cogr_featuredefn == NULL:
             raise ValueError("Null feature definition")
-        n = ograpi.OGR_FD_GetFieldCount(cogr_featuredefn)
+        n = ogrext1.OGR_FD_GetFieldCount(cogr_featuredefn)
         for i from 0 <= i < n:
-            cogr_fielddefn = ograpi.OGR_FD_GetFieldDefn(cogr_featuredefn, i)
+            cogr_fielddefn = ogrext1.OGR_FD_GetFieldDefn(cogr_featuredefn, i)
             if cogr_fielddefn == NULL:
                 raise ValueError("Null field definition")
-            key_c = ograpi.OGR_Fld_GetNameRef(cogr_fielddefn)
+            key_c = ogrext1.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)]
+            fieldtypename = FIELD_TYPES[ogrext1.OGR_Fld_GetType(cogr_fielddefn)]
             if not fieldtypename:
                 log.warn(
                     "Skipping field %s: invalid type %s", 
                     key,
-                    ograpi.OGR_Fld_GetType(cogr_fielddefn))
+                    ogrext1.OGR_Fld_GetType(cogr_fielddefn))
                 continue
             val = fieldtypename
             if fieldtypename == 'float':
                 fmt = ""
-                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
+                width = ogrext1.OGR_Fld_GetWidth(cogr_fielddefn)
                 if width: # and width != 24:
                     fmt = ":%d" % width
-                precision = ograpi.OGR_Fld_GetPrecision(cogr_fielddefn)
+                precision = ogrext1.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)
+                width = ogrext1.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)
+                width = ogrext1.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(
+        cdef unsigned int geom_type = ogrext1.OGR_FD_GetGeomType(
             cogr_featuredefn)
         return {
             'properties': OrderedDict(props), 
@@ -546,17 +546,17 @@ cdef class Session:
         cdef void *cogr_crs = NULL
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
+        cogr_crs = ogrext1.OGR_L_GetSpatialRef(self.cogr_layer)
         crs = {}
         if cogr_crs is not NULL:
             log.debug("Got coordinate system")
 
-            retval = ograpi.OSRAutoIdentifyEPSG(cogr_crs)
+            retval = ogrext1.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)
+            auth_key = ogrext1.OSRGetAuthorityName(cogr_crs, NULL)
+            auth_val = ogrext1.OSRGetAuthorityCode(cogr_crs, NULL)
 
             if auth_key != NULL and auth_val != NULL:
                 key_b = auth_key
@@ -566,7 +566,7 @@ cdef class Session:
                     val = val_b.decode('utf-8')
                     crs['init'] = "epsg:" + val
             else:
-                ograpi.OSRExportToProj4(cogr_crs, &proj_c)
+                ogrext1.OSRExportToProj4(cogr_crs, &proj_c)
                 if proj_c == NULL:
                     raise ValueError("Null projection")
                 proj_b = proj_c
@@ -591,7 +591,7 @@ cdef class Session:
                     k = k.lstrip("+")
                     crs[k] = v
 
-            ograpi.CPLFree(proj_c)
+            ogrext1.CPLFree(proj_c)
         else:
             log.debug("Projection not found (cogr_crs was NULL)")
         return crs
@@ -600,16 +600,16 @@ cdef class Session:
         cdef char *proj_c = NULL
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
+        cogr_crs = ogrext1.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)
+            ogrext1.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)
+            ogrext1.CPLFree(proj_c)
         else:
             log.debug("Projection not found (cogr_crs was NULL)")
         return crs_wkt
@@ -617,8 +617,8 @@ cdef class Session:
     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)
+        cdef ogrext1.OGREnvelope extent
+        result = ogrext1.OGR_L_GetExtent(self.cogr_layer, &extent, 1)
         return (extent.MinX, extent.MinY, extent.MaxX, extent.MaxY)
 
     def has_feature(self, fid):
@@ -628,7 +628,7 @@ cdef class Session:
         """
         cdef void * cogr_feature
         fid = int(fid)
-        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
+        cogr_feature = ogrext1.OGR_L_GetFeature(self.cogr_layer, fid)
         if cogr_feature != NULL:
             _deleteOgrFeature(cogr_feature)
             return True
@@ -642,7 +642,7 @@ cdef class Session:
         """
         cdef void * cogr_feature
         fid = int(fid)
-        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
+        cogr_feature = ogrext1.OGR_L_GetFeature(self.cogr_layer, fid)
         if cogr_feature != NULL:
             _deleteOgrFeature(cogr_feature)
             return True
@@ -660,12 +660,12 @@ cdef class Session:
             index = item
             # from the back
             if index < 0:
-                ftcount = ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
+                ftcount = ogrext1.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)
+            cogr_feature = ogrext1.OGR_L_GetFeature(self.cogr_layer, index)
             if cogr_feature == NULL:
                 return None
             feature = FeatureBuilder().build(
@@ -712,20 +712,20 @@ cdef class WritingSession(Session):
                     path_b = path
                 path_c = path_b
                 with cpl_errs:
-                    self.cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
+                    self.cogr_ds = ogrext1.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)
+                cogr_driver = ogrext1.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_layer = ogrext1.OGR_DS_GetLayerByName(
                                         self.cogr_ds, name_c)
                 elif isinstance(collection.name, int):
-                    self.cogr_layer = ograpi.OGR_DS_GetLayer(
+                    self.cogr_layer = ogrext1.OGR_DS_GetLayer(
                                         self.cogr_ds, collection.name)
 
                 if self.cogr_layer == NULL:
@@ -736,7 +736,7 @@ cdef class WritingSession(Session):
 
             userencoding = self.collection.encoding
             self._fileencoding = (userencoding or (
-                ograpi.OGR_L_TestCapability(self.cogr_layer, OLC_STRINGSASUTF8) and
+                ogrext1.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()
@@ -750,27 +750,27 @@ cdef class WritingSession(Session):
             driver_b = collection.driver.encode()
             driver_c = driver_b
 
-            cogr_driver = ograpi.OGRGetDriverByName(driver_c)
+            cogr_driver = ogrext1.OGRGetDriverByName(driver_c)
             if cogr_driver == NULL:
                 raise ValueError("Null driver")
 
             if not os.path.exists(path):
-                cogr_ds = ograpi.OGR_Dr_CreateDataSource(
+                cogr_ds = ogrext1.OGR_Dr_CreateDataSource(
                     cogr_driver, path_c, NULL)
 
             else:
                 with cpl_errs:
-                    cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
+                    cogr_ds = ogrext1.OGROpen(path_c, 1, NULL)
                 if cogr_ds == NULL:
-                    cogr_ds = ograpi.OGR_Dr_CreateDataSource(
+                    cogr_ds = ogrext1.OGR_Dr_CreateDataSource(
                         cogr_driver, path_c, NULL)
 
                 elif collection.name is None:
-                    ograpi.OGR_DS_Destroy(cogr_ds)
+                    ogrext1.OGR_DS_Destroy(cogr_ds)
                     cogr_ds == NULL
                     log.debug("Deleted pre-existing data at %s", path)
                     
-                    cogr_ds = ograpi.OGR_Dr_CreateDataSource(
+                    cogr_ds = ogrext1.OGR_Dr_CreateDataSource(
                         cogr_driver, path_c, NULL)
 
                 else:
@@ -787,14 +787,14 @@ cdef class WritingSession(Session):
             # is constructed (later).
             col_crs = collection._crs_wkt or collection._crs
             if col_crs:
-                cogr_srs = ograpi.OSRNewSpatialReference(NULL)
+                cogr_srs = ogrext1.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)
+                    ogrext1.OSRSetFromUserInput(cogr_srs, proj_c)
                 elif isinstance(col_crs, dict):
                     # EPSG is a special case.
                     init = col_crs.get('init')
@@ -803,7 +803,7 @@ cdef class WritingSession(Session):
                         auth, val = init.split(':')
                         if auth.upper() == 'EPSG':
                             log.debug("Setting EPSG: %s", val)
-                            ograpi.OSRImportFromEPSG(cogr_srs, int(val))
+                            ogrext1.OSRImportFromEPSG(cogr_srs, int(val))
                     else:
                         params = []
                         col_crs['wktext'] = True
@@ -816,12 +816,12 @@ cdef class WritingSession(Session):
                         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)
+                        ogrext1.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)
+                ogrext1.OSRFixup(cogr_srs)
 
             # Figure out what encoding to use. The encoding parameter given
             # to the collection constructor takes highest precedence, then
@@ -836,15 +836,15 @@ cdef class WritingSession(Session):
             if fileencoding:
                 fileencoding_b = fileencoding.encode('utf-8')
                 fileencoding_c = fileencoding_b
-                options = ograpi.CSLSetNameValue(options, "ENCODING", fileencoding_c)
+                options = ogrext1.CSLSetNameValue(options, "ENCODING", fileencoding_c)
                 log.debug("Output file encoding: %s", fileencoding)
 
             # Does the layer exist already? If so, we delete it.
-            layer_count = ograpi.OGR_DS_GetLayerCount(self.cogr_ds)
+            layer_count = ogrext1.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)
+                cogr_layer = ogrext1.OGR_DS_GetLayer(cogr_ds, i)
+                name_c = ogrext1.OGR_L_GetName(cogr_layer)
                 name_b = name_c
                 layer_names.append(name_b.decode('utf-8'))
 
@@ -857,12 +857,12 @@ cdef class WritingSession(Session):
                     idx = collection.name
             if idx >= 0:
                 log.debug("Deleted pre-existing layer at %s", collection.name)
-                ograpi.OGR_DS_DeleteLayer(self.cogr_ds, idx)
+                ogrext1.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_layer = ogrext1.OGR_DS_CreateLayer(
                 self.cogr_ds,
                 name_c,
                 cogr_srs,
@@ -872,9 +872,9 @@ cdef class WritingSession(Session):
                 )
 
             if cogr_srs != NULL:
-                ograpi.OSRDestroySpatialReference(cogr_srs)
+                ogrext1.OSRDestroySpatialReference(cogr_srs)
             if options != NULL:
-                ograpi.CSLDestroy(options)
+                ogrext1.CSLDestroy(options)
 
             if self.cogr_layer == NULL:
                 raise ValueError("Null layer")
@@ -901,17 +901,17 @@ cdef class WritingSession(Session):
                 
                 encoding = self.get_internalencoding()
                 key_bytes = key.encode(encoding)
-                cogr_fielddefn = ograpi.OGR_Fld_Create(
+                cogr_fielddefn = ogrext1.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)
+                    ogrext1.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)
+                    ogrext1.OGR_Fld_SetPrecision(cogr_fielddefn, precision)
+                ogrext1.OGR_L_CreateField(self.cogr_layer, cogr_fielddefn, 1)
+                ogrext1.OGR_Fld_Destroy(cogr_fielddefn)
             log.debug("Created fields")
 
         # Mapping of the Python collection schema to the munged 
@@ -933,11 +933,11 @@ cdef class WritingSession(Session):
             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":
+        cogr_driver = ogrext1.OGR_DS_GetDriver(self.cogr_ds)
+        if ogrext1.OGR_Dr_GetName(cogr_driver) == b"GeoJSON":
             def validate_geometry_type(rec):
                 return True
-        elif ograpi.OGR_Dr_GetName(cogr_driver) == b"ESRI Shapefile" \
+        elif ogrext1.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")
@@ -968,7 +968,7 @@ cdef class WritingSession(Session):
                          collection.schema['geometry'] ))
 
             cogr_feature = OGRFeatureBuilder().build(record, collection)
-            result = ograpi.OGR_L_CreateFeature(cogr_layer, cogr_feature)
+            result = ogrext1.OGR_L_CreateFeature(cogr_layer, cogr_feature)
             if result != OGRERR_NONE:
                 raise RuntimeError("Failed to write record: %s" % record)
             _deleteOgrFeature(cogr_feature)
@@ -980,7 +980,7 @@ cdef class WritingSession(Session):
         if cogr_ds == NULL:
             raise ValueError("Null data source")
         log.debug("Syncing OGR to disk")
-        retval = ograpi.OGR_DS_SyncToDisk(cogr_ds)
+        retval = ogrext1.OGR_DS_SyncToDisk(cogr_ds)
         if retval != OGRERR_NONE:
             raise RuntimeError("Failed to sync to disk")
 
@@ -1000,8 +1000,8 @@ cdef class Iterator:
     cdef fastindex
     cdef stepsign
 
-    def __init__(self, collection, 
-            start=None, stop=None, step=None, bbox=None, mask=None):
+    def __cinit__(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
@@ -1011,28 +1011,28 @@ cdef class Iterator:
         cdef void *cogr_layer = session.cogr_layer
         if cogr_layer == NULL:
             raise ValueError("Null layer")
-        ograpi.OGR_L_ResetReading(cogr_layer)
+        ogrext1.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(
+            ogrext1.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)
+            ogrext1.OGR_L_SetSpatialFilter(cogr_layer, cogr_geometry)
+            ogrext1.OGR_G_DestroyGeometry(cogr_geometry)
             
         else:
-            ograpi.OGR_L_SetSpatialFilter(
+            ogrext1.OGR_L_SetSpatialFilter(
                 cogr_layer, NULL)
         self.encoding = session.get_internalencoding()
 
-        self.fastindex = ograpi.OGR_L_TestCapability(
+        self.fastindex = ogrext1.OGR_L_TestCapability(
             session.cogr_layer, OLC_FASTSETNEXTBYINDEX)
 
-        ftcount = ograpi.OGR_L_GetFeatureCount(session.cogr_layer, 0)
+        ftcount = ogrext1.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(
@@ -1062,7 +1062,7 @@ cdef class Iterator:
 
         self.next_index = start
         log.debug("Index: %d", self.next_index)
-        ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
+        ogrext1.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
 
 
     def __iter__(self):
@@ -1089,22 +1089,22 @@ cdef class Iterator:
 
         # Set read cursor to next_item position
         if self.step > 1 and self.fastindex:
-            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
+            ogrext1.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)
+                cogr_feature = ogrext1.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)
+            ogrext1.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
 
         elif self.step == 0:
-            # ograpi.OGR_L_GetNextFeature increments read cursor by one
+            # ogrext1.OGR_L_GetNextFeature increments read cursor by one
             pass
         elif self.step < 0:
-            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
+            ogrext1.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
             
         # set the next index
         self.next_index += self.step
@@ -1119,7 +1119,7 @@ cdef class Iterator:
         self._next()
 
         # Get the next feature.
-        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
+        cogr_feature = ogrext1.OGR_L_GetNextFeature(session.cogr_layer)
         if cogr_feature == NULL:
             raise StopIteration
 
@@ -1146,12 +1146,12 @@ cdef class ItemsIterator(Iterator):
         self._next()
 
         # Get the next feature.
-        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
+        cogr_feature = ogrext1.OGR_L_GetNextFeature(session.cogr_layer)
         if cogr_feature == NULL:
             raise StopIteration
 
 
-        fid = ograpi.OGR_F_GetFID(cogr_feature)
+        fid = ogrext1.OGR_F_GetFID(cogr_feature)
         feature = FeatureBuilder().build(
             cogr_feature,
             bbox=False,
@@ -1175,11 +1175,11 @@ cdef class KeysIterator(Iterator):
         self._next()
 
         # Get the next feature.
-        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
+        cogr_feature = ogrext1.OGR_L_GetNextFeature(session.cogr_layer)
         if cogr_feature == NULL:
             raise StopIteration
 
-        fid = ograpi.OGR_F_GetFID(cogr_feature)
+        fid = ogrext1.OGR_F_GetFID(cogr_feature)
         _deleteOgrFeature(cogr_feature)
 
         return fid
@@ -1194,14 +1194,14 @@ def _remove(path, driver=None):
     if driver is None:
         driver = 'ESRI Shapefile'
 
-    cogr_driver = ograpi.OGRGetDriverByName(driver.encode('utf-8'))
+    cogr_driver = ogrext1.OGRGetDriverByName(driver.encode('utf-8'))
     if cogr_driver == NULL:
         raise ValueError("Null driver")
 
-    if not ograpi.OGR_Dr_TestCapability(cogr_driver, ODrCDeleteDataSource):
+    if not ogrext1.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'))
+    result = ogrext1.OGR_Dr_DeleteDataSource(cogr_driver, path.encode('utf-8'))
     if result != OGRERR_NONE:
         raise RuntimeError("Failed to remove data source {}".format(path))
 
@@ -1223,22 +1223,22 @@ def _listlayers(path):
         path_b = path
     path_c = path_b
     with cpl_errs:
-        cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
+        cogr_ds = ogrext1.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_count = ogrext1.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)
+        cogr_layer = ogrext1.OGR_DS_GetLayer(cogr_ds, i)
+        name_c = ogrext1.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)
+        ogrext1.OGR_DS_Destroy(cogr_ds)
     cogr_ds = NULL
 
     return layer_names
@@ -1249,16 +1249,16 @@ def buffer_to_virtual_file(bytesbuf):
     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)
+    vsi_handle = ogrext1.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:
+    if ogrext1.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)
+    return ogrext1.VSIUnlink(vsi_cfilename)
 
 
diff --git a/fiona/ograpi2.pxd b/fiona/ogrext2.pxd
similarity index 100%
rename from fiona/ograpi2.pxd
rename to fiona/ogrext2.pxd
diff --git a/fiona/ogrext2.pyx b/fiona/ogrext2.pyx
index 9172bb9..3eecd31 100644
--- a/fiona/ogrext2.pyx
+++ b/fiona/ogrext2.pyx
@@ -12,8 +12,8 @@ import uuid
 
 from six import integer_types, string_types, text_type
 
-from fiona cimport ograpi
-from fiona._geometry cimport GeomBuilder, OGRGeomBuilder
+cimport ogrext2
+from _geometry cimport GeomBuilder, OGRGeomBuilder
 from fiona._err import cpl_errs
 from fiona._geometry import GEOMETRY_TYPES
 from fiona.errors import DriverError, SchemaError, CRSError, FionaValueError
@@ -138,11 +138,11 @@ def calc_gdal_version_num(maj, min, rev):
 
 def get_gdal_version_num():
     """Return current internal version number of gdal"""
-    return int(ograpi.GDALVersionInfo("VERSION_NUM"))
+    return int(ogrext2.GDALVersionInfo("VERSION_NUM"))
 
 def get_gdal_release_name():
     """Return release name of gdal"""
-    return ograpi.GDALVersionInfo("RELEASE_NAME")
+    return ogrext2.GDALVersionInfo("RELEASE_NAME")
 
 
 # Feature extension classes and functions follow.
@@ -168,35 +168,35 @@ cdef class FeatureBuilder:
         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)
+        for i in range(ogrext2.OGR_F_GetFieldCount(feature)):
+            fdefn = ogrext2.OGR_F_GetFieldDefnRef(feature, i)
             if fdefn == NULL:
                 raise ValueError("Null feature definition")
-            key_c = ograpi.OGR_Fld_GetNameRef(fdefn)
+            key_c = ogrext2.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)]
+            fieldtypename = FIELD_TYPES[ogrext2.OGR_Fld_GetType(fdefn)]
             if not fieldtypename:
                 log.warn(
                     "Skipping field %s: invalid type %s", 
                     key,
-                    ograpi.OGR_Fld_GetType(fdefn))
+                    ogrext2.OGR_Fld_GetType(fdefn))
                 continue
 
             # TODO: other types
             fieldtype = FIELD_TYPES_MAP[fieldtypename]
-            if not ograpi.OGR_F_IsFieldSet(feature, i):
+            if not ogrext2.OGR_F_IsFieldSet(feature, i):
                 props[key] = None
             elif fieldtype is int:
-                props[key] = ograpi.OGR_F_GetFieldAsInteger64(feature, i)
+                props[key] = ogrext2.OGR_F_GetFieldAsInteger64(feature, i)
             elif fieldtype is float:
-                props[key] = ograpi.OGR_F_GetFieldAsDouble(feature, i)
+                props[key] = ogrext2.OGR_F_GetFieldAsDouble(feature, i)
 
             elif fieldtype is text_type:
                 try:
-                    val = ograpi.OGR_F_GetFieldAsString(feature, i)
+                    val = ogrext2.OGR_F_GetFieldAsString(feature, i)
                     val = val.decode(encoding)
                 except UnicodeDecodeError:
                     log.warn(
@@ -214,7 +214,7 @@ cdef class FeatureBuilder:
                 props[key] = val
 
             elif fieldtype in (FionaDateType, FionaTimeType, FionaDateTimeType):
-                retval = ograpi.OGR_F_GetFieldAsDateTime(
+                retval = ogrext2.OGR_F_GetFieldAsDateTime(
                     feature, i, &y, &m, &d, &hh, &mm, &ss, &tz)
                 if fieldtype is FionaDateType:
                     props[key] = datetime.date(y, m, d).isoformat()
@@ -227,14 +227,14 @@ cdef class FeatureBuilder:
                 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)
+        cdef void *cogr_geometry = ogrext2.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)),
+            'id': str(ogrext2.OGR_F_GetFID(feature)),
             'geometry': geom,
             'properties': props }
 
@@ -255,17 +255,17 @@ cdef class OGRFeatureBuilder:
         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)
+        cdef void *cogr_featuredefn = ogrext2.OGR_L_GetLayerDefn(cogr_layer)
         if cogr_featuredefn == NULL:
             raise ValueError("Null feature definition")
-        cdef void *cogr_feature = ograpi.OGR_F_Create(cogr_featuredefn)
+        cdef void *cogr_feature = ogrext2.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)
+        ogrext2.OGR_F_SetGeometryDirectly(cogr_feature, cogr_geometry)
         
         # OGR_F_SetFieldString takes UTF-8 encoded strings ('bytes' in 
         # Python 3).
@@ -282,7 +282,7 @@ cdef class OGRFeatureBuilder:
                 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)
+            i = ogrext2.OGR_F_GetFieldIndex(cogr_feature, key_c)
             if i < 0:
                 continue
 
@@ -292,9 +292,9 @@ cdef class OGRFeatureBuilder:
 
             # Continue over the standard OGR types.
             if isinstance(value, integer_types):
-                ograpi.OGR_F_SetFieldInteger64(cogr_feature, i, value)
+                ogrext2.OGR_F_SetFieldInteger64(cogr_feature, i, value)
             elif isinstance(value, float):
-                ograpi.OGR_F_SetFieldDouble(cogr_feature, i, value)
+                ogrext2.OGR_F_SetFieldDouble(cogr_feature, i, value)
             elif (isinstance(value, string_types) 
             and schema_type in ['date', 'time', 'datetime']):
                 if schema_type == 'date':
@@ -303,23 +303,23 @@ cdef class OGRFeatureBuilder:
                     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(
+                ogrext2.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(
+                ogrext2.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(
+                ogrext2.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(
+                ogrext2.OGR_F_SetFieldDateTime(
                     cogr_feature, i, 0, 0, 0, hh, mm, ss, 0)
             elif isinstance(value, string_types):
                 try:
@@ -329,7 +329,7 @@ cdef class OGRFeatureBuilder:
                         "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)
+                ogrext2.OGR_F_SetFieldString(cogr_feature, i, string_c)
             elif value is None:
                 pass # keep field unset/null
             else:
@@ -341,17 +341,17 @@ cdef class OGRFeatureBuilder:
 cdef _deleteOgrFeature(void *cogr_feature):
     """Delete an OGR feature"""
     if cogr_feature is not NULL:
-        ograpi.OGR_F_Destroy(cogr_feature)
+        ogrext2.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)
+    cdef void *cogr_geometry = ogrext2.OGR_F_GetGeometryRef(cogr_feature)
     if cogr_geometry == NULL:
         raise ValueError("Null geometry")
-    log.debug("Geometry: %s" % ograpi.OGR_G_ExportToJson(cogr_geometry))
+    log.debug("Geometry: %s" % ogrext2.OGR_G_ExportToJson(cogr_geometry))
     encoding = collection.encoding or 'utf-8'
     result = FeatureBuilder().build(
         cogr_feature,
@@ -373,7 +373,7 @@ cdef class Session:
     cdef object _encoding
     cdef object collection
 
-    def __cinit__(self):
+    def __init__(self):
         self.cogr_ds = NULL
         self.cogr_layer = NULL
         self._fileencoding = None
@@ -410,13 +410,13 @@ cdef class Session:
                     name_b = name.encode()
                     name_c = name_b
                     log.debug("Trying driver: %s", name)
-                    drv = ograpi.GDALGetDriverByName(name_c)
+                    drv = ogrext2.GDALGetDriverByName(name_c)
                     if drv != NULL:
                         drvs = string_list([name_b])
 
-                        flags = ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_READONLY
+                        flags = ogrext2.GDAL_OF_VECTOR | ogrext2.GDAL_OF_READONLY
                         log.debug("GDALOpenEx({}, {}, {})".format(path_c, flags, [name_b]))
-                        ds = ograpi.GDALOpenEx(path_c,
+                        ds = ogrext2.GDALOpenEx(path_c,
                                                flags,
                                                drvs,
                                                NULL,
@@ -425,14 +425,14 @@ cdef class Session:
                     if ds != NULL:
                         self.cogr_ds = ds
                         collection._driver = name
-                        _driver = ograpi.GDALGetDatasetDriver(ds)
-                        drv_name = ograpi.GDALGetDriverShortName(_driver)
+                        _driver = ogrext2.GDALGetDatasetDriver(ds)
+                        drv_name = ogrext2.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,
+                self.cogr_ds = ogrext2.GDALOpenEx(path_c,
+                                                 ogrext2.GDAL_OF_VECTOR | ogrext2.GDAL_OF_READONLY,
                                                  NULL,
                                                  NULL,
                                                  NULL)
@@ -446,12 +446,12 @@ cdef class Session:
         if isinstance(collection.name, string_types):
             name_b = collection.name.encode('utf-8')
             name_c = name_b
-            self.cogr_layer = ograpi.GDALDatasetGetLayerByName(
+            self.cogr_layer = ogrext2.GDALDatasetGetLayerByName(
                                 self.cogr_ds, name_c)
         elif isinstance(collection.name, int):
-            self.cogr_layer = ograpi.GDALDatasetGetLayer(
+            self.cogr_layer = ogrext2.GDALDatasetGetLayer(
                                 self.cogr_ds, collection.name)
-            name_c = ograpi.OGR_L_GetName(self.cogr_layer)
+            name_c = ogrext2.OGR_L_GetName(self.cogr_layer)
             name_b = name_c
             collection.name = name_b.decode('utf-8')
 
@@ -462,11 +462,11 @@ cdef class Session:
         
         userencoding = self.collection.encoding
         if userencoding:
-            ograpi.CPLSetThreadLocalConfigOption('SHAPE_ENCODING', '')
+            ogrext2.CPLSetThreadLocalConfigOption('SHAPE_ENCODING', '')
             self._fileencoding = userencoding.upper()
         else:
             self._fileencoding = (
-                ograpi.OGR_L_TestCapability(
+                ogrext2.OGR_L_TestCapability(
                     self.cogr_layer, OLC_STRINGSASUTF8) and
                 'utf-8') or (
                 self.get_driver() == "ESRI Shapefile" and
@@ -475,7 +475,7 @@ cdef class Session:
     def stop(self):
         self.cogr_layer = NULL
         if self.cogr_ds is not NULL:
-            ograpi.GDALClose(self.cogr_ds)
+            ogrext2.GDALClose(self.cogr_ds)
         self.cogr_ds = NULL
 
     def get_fileencoding(self):
@@ -485,7 +485,7 @@ cdef class Session:
         if not self._encoding:
             fileencoding = self.get_fileencoding()
             self._encoding = (
-                ograpi.OGR_L_TestCapability(
+                ogrext2.OGR_L_TestCapability(
                     self.cogr_layer, OLC_STRINGSASUTF8) and
                 'utf-8') or fileencoding
         return self._encoding
@@ -493,13 +493,13 @@ cdef class Session:
     def get_length(self):
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        return ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
+        return ogrext2.OGR_L_GetFeatureCount(self.cogr_layer, 0)
 
     def get_driver(self):
-        cdef void *cogr_driver = ograpi.GDALGetDatasetDriver(self.cogr_ds)
+        cdef void *cogr_driver = ogrext2.GDALGetDatasetDriver(self.cogr_ds)
         if cogr_driver == NULL:
             raise ValueError("Null driver")
-        cdef char *name = ograpi.OGR_Dr_GetName(cogr_driver)
+        cdef char *name = ogrext2.OGR_Dr_GetName(cogr_driver)
         driver_name = name
         return driver_name.decode()
  
@@ -514,52 +514,52 @@ cdef class Session:
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
 
-        cogr_featuredefn = ograpi.OGR_L_GetLayerDefn(self.cogr_layer)
+        cogr_featuredefn = ogrext2.OGR_L_GetLayerDefn(self.cogr_layer)
         if cogr_featuredefn == NULL:
             raise ValueError("Null feature definition")
-        n = ograpi.OGR_FD_GetFieldCount(cogr_featuredefn)
+        n = ogrext2.OGR_FD_GetFieldCount(cogr_featuredefn)
         for i from 0 <= i < n:
-            cogr_fielddefn = ograpi.OGR_FD_GetFieldDefn(cogr_featuredefn, i)
+            cogr_fielddefn = ogrext2.OGR_FD_GetFieldDefn(cogr_featuredefn, i)
             if cogr_fielddefn == NULL:
                 raise ValueError("Null field definition")
-            key_c = ograpi.OGR_Fld_GetNameRef(cogr_fielddefn)
+            key_c = ogrext2.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)]
+            fieldtypename = FIELD_TYPES[ogrext2.OGR_Fld_GetType(cogr_fielddefn)]
             if not fieldtypename:
                 log.warn(
                     "Skipping field %s: invalid type %s", 
                     key,
-                    ograpi.OGR_Fld_GetType(cogr_fielddefn))
+                    ogrext2.OGR_Fld_GetType(cogr_fielddefn))
                 continue
             val = fieldtypename
             if fieldtypename == 'float':
                 fmt = ""
-                width = ograpi.OGR_Fld_GetWidth(cogr_fielddefn)
+                width = ogrext2.OGR_Fld_GetWidth(cogr_fielddefn)
                 if width: # and width != 24:
                     fmt = ":%d" % width
-                precision = ograpi.OGR_Fld_GetPrecision(cogr_fielddefn)
+                precision = ogrext2.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)
+                width = ogrext2.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)
+                width = ogrext2.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(
+        cdef unsigned int geom_type = ogrext2.OGR_FD_GetGeomType(
             cogr_featuredefn)
         return {
             'properties': OrderedDict(props), 
@@ -572,17 +572,17 @@ cdef class Session:
         cdef void *cogr_crs = NULL
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
+        cogr_crs = ogrext2.OGR_L_GetSpatialRef(self.cogr_layer)
         crs = {}
         if cogr_crs is not NULL:
             log.debug("Got coordinate system")
 
-            retval = ograpi.OSRAutoIdentifyEPSG(cogr_crs)
+            retval = ogrext2.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)
+            auth_key = ogrext2.OSRGetAuthorityName(cogr_crs, NULL)
+            auth_val = ogrext2.OSRGetAuthorityCode(cogr_crs, NULL)
 
             if auth_key != NULL and auth_val != NULL:
                 key_b = auth_key
@@ -592,7 +592,7 @@ cdef class Session:
                     val = val_b.decode('utf-8')
                     crs['init'] = "epsg:" + val
             else:
-                ograpi.OSRExportToProj4(cogr_crs, &proj_c)
+                ogrext2.OSRExportToProj4(cogr_crs, &proj_c)
                 if proj_c == NULL:
                     raise ValueError("Null projection")
                 proj_b = proj_c
@@ -617,7 +617,7 @@ cdef class Session:
                     k = k.lstrip("+")
                     crs[k] = v
 
-            ograpi.CPLFree(proj_c)
+            ogrext2.CPLFree(proj_c)
         else:
             log.debug("Projection not found (cogr_crs was NULL)")
         return crs
@@ -626,16 +626,16 @@ cdef class Session:
         cdef char *proj_c = NULL
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        cogr_crs = ograpi.OGR_L_GetSpatialRef(self.cogr_layer)
+        cogr_crs = ogrext2.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)
+            ogrext2.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)
+            ogrext2.CPLFree(proj_c)
         else:
             log.debug("Projection not found (cogr_crs was NULL)")        
         return crs_wkt
@@ -643,8 +643,8 @@ cdef class Session:
     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)
+        cdef ogrext2.OGREnvelope extent
+        result = ogrext2.OGR_L_GetExtent(self.cogr_layer, &extent, 1)
         return (extent.MinX, extent.MinY, extent.MaxX, extent.MaxY)
 
     def has_feature(self, fid):
@@ -654,7 +654,7 @@ cdef class Session:
         """
         cdef void * cogr_feature
         fid = int(fid)
-        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
+        cogr_feature = ogrext2.OGR_L_GetFeature(self.cogr_layer, fid)
         if cogr_feature != NULL:
             _deleteOgrFeature(cogr_feature)
             return True
@@ -668,7 +668,7 @@ cdef class Session:
         """
         cdef void * cogr_feature
         fid = int(fid)
-        cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
+        cogr_feature = ogrext2.OGR_L_GetFeature(self.cogr_layer, fid)
         if cogr_feature != NULL:
             _deleteOgrFeature(cogr_feature)
             return True
@@ -686,12 +686,12 @@ cdef class Session:
             index = item
             # from the back
             if index < 0:
-                ftcount = ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
+                ftcount = ogrext2.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)
+            cogr_feature = ogrext2.OGR_L_GetFeature(self.cogr_layer, index)
             if cogr_feature == NULL:
                 return None
             feature = FeatureBuilder().build(
@@ -738,25 +738,25 @@ cdef class WritingSession(Session):
                     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,
+                    self.cogr_ds = ogrext2.GDALOpenEx(path_c,
+                                                 ogrext2.GDAL_OF_VECTOR | ogrext2.GDAL_OF_UPDATE,
                                                  NULL,
                                                  NULL,
                                                  NULL)
-#                     self.cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
+#                     self.cogr_ds = ogrext2.OGROpen(path_c, 1, NULL)
                 if self.cogr_ds == NULL:
                     raise RuntimeError("Failed to open %s" % path)
-                cogr_driver = ograpi.GDALGetDatasetDriver(self.cogr_ds)
+                cogr_driver = ogrext2.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_layer = ogrext2.GDALDatasetGetLayerByName(
                                         self.cogr_ds, name_c)
                 elif isinstance(collection.name, int):
-                    self.cogr_layer = ograpi.GDALDatasetGetLayer(
+                    self.cogr_layer = ogrext2.GDALDatasetGetLayer(
                                         self.cogr_ds, collection.name)
 
                 if self.cogr_layer == NULL:
@@ -767,7 +767,7 @@ cdef class WritingSession(Session):
 
             userencoding = self.collection.encoding
             self._fileencoding = (userencoding or (
-                ograpi.OGR_L_TestCapability(self.cogr_layer, OLC_STRINGSASUTF8) and
+                ogrext2.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()
@@ -781,56 +781,56 @@ cdef class WritingSession(Session):
             driver_b = collection.driver.encode()
             driver_c = driver_b
 
-            cogr_driver = ograpi.GDALGetDriverByName(driver_c)
+            cogr_driver = ogrext2.GDALGetDriverByName(driver_c)
             if cogr_driver == NULL:
                 raise ValueError("Null driver")
 
             if not os.path.exists(path):
-#                 cogr_ds = ograpi.OGR_Dr_CreateDataSource(
+#                 cogr_ds = ogrext2.OGR_Dr_CreateDataSource(
 #                     cogr_driver, path_c, NULL)
-                cogr_ds = ograpi.GDALCreate(
+                cogr_ds = ogrext2.GDALCreate(
                     cogr_driver,
                     path_c,
                     0,
                     0,
                     0,
-                    ograpi.GDT_Unknown,
+                    ogrext2.GDT_Unknown,
                     NULL)
                 pass
 
             else:
                 with cpl_errs:
-                    cogr_ds = ograpi.GDALOpenEx(path_c,
-                                     ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_UPDATE,
+                    cogr_ds = ogrext2.GDALOpenEx(path_c,
+                                     ogrext2.GDAL_OF_VECTOR | ogrext2.GDAL_OF_UPDATE,
                                      NULL,
                                      NULL,
                                      NULL)
-#                     cogr_ds = ograpi.OGROpen(path_c, 1, NULL)
+#                     cogr_ds = ogrext2.OGROpen(path_c, 1, NULL)
                 if cogr_ds == NULL:
-                    cogr_ds = ograpi.GDALCreate(
+                    cogr_ds = ogrext2.GDALCreate(
                         cogr_driver,
                         path_c,
                         0,
                         0,
                         0,
-                        ograpi.GDT_Unknown,
+                        ogrext2.GDT_Unknown,
                         NULL)
-#                     cogr_ds = ograpi.OGR_Dr_CreateDataSource(
+#                     cogr_ds = ogrext2.OGR_Dr_CreateDataSource(
 #                         cogr_driver, path_c, NULL)
 
                 elif collection.name is None:
-                    ograpi.GDALClose(cogr_ds)
+                    ogrext2.GDALClose(cogr_ds)
                     cogr_ds == NULL
                     log.debug("Deleted pre-existing data at %s", path)
-                    cogr_ds = ograpi.GDALCreate(
+                    cogr_ds = ogrext2.GDALCreate(
                         cogr_driver,
                         path_c,
                         0,
                         0,
                         0,
-                        ograpi.GDT_Unknown,
+                        ogrext2.GDT_Unknown,
                         NULL)
-#                     cogr_ds = ograpi.OGR_Dr_CreateDataSource(
+#                     cogr_ds = ogrext2.OGR_Dr_CreateDataSource(
 #                         cogr_driver, path_c, NULL)
 
                 else:
@@ -847,14 +847,14 @@ cdef class WritingSession(Session):
             # is constructed (later).
             col_crs = collection._crs_wkt or collection._crs
             if col_crs:
-                cogr_srs = ograpi.OSRNewSpatialReference(NULL)
+                cogr_srs = ogrext2.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)
+                    ogrext2.OSRSetFromUserInput(cogr_srs, proj_c)
                 elif isinstance(col_crs, dict):
                     # EPSG is a special case.
                     init = col_crs.get('init')
@@ -863,7 +863,7 @@ cdef class WritingSession(Session):
                         auth, val = init.split(':')
                         if auth.upper() == 'EPSG':
                             log.debug("Setting EPSG: %s", val)
-                            ograpi.OSRImportFromEPSG(cogr_srs, int(val))
+                            ogrext2.OSRImportFromEPSG(cogr_srs, int(val))
                     else:
                         params = []
                         col_crs['wktext'] = True
@@ -876,12 +876,12 @@ cdef class WritingSession(Session):
                         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)
+                        ogrext2.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)
+                ogrext2.OSRFixup(cogr_srs)
 
             # Figure out what encoding to use. The encoding parameter given
             # to the collection constructor takes highest precedence, then
@@ -896,14 +896,14 @@ cdef class WritingSession(Session):
             if fileencoding:
                 fileencoding_b = fileencoding.encode()
                 fileencoding_c = fileencoding_b
-                options = ograpi.CSLSetNameValue(options, "ENCODING", fileencoding_c)
+                options = ogrext2.CSLSetNameValue(options, "ENCODING", fileencoding_c)
 
             # Does the layer exist already? If so, we delete it.
-            layer_count = ograpi.GDALDatasetGetLayerCount(self.cogr_ds)
+            layer_count = ogrext2.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)
+                cogr_layer = ogrext2.GDALDatasetGetLayer(cogr_ds, i)
+                name_c = ogrext2.OGR_L_GetName(cogr_layer)
                 name_b = name_c
                 layer_names.append(name_b.decode('utf-8'))
 
@@ -916,12 +916,12 @@ cdef class WritingSession(Session):
                     idx = collection.name
             if idx >= 0:
                 log.debug("Deleted pre-existing layer at %s", collection.name)
-                ograpi.GDALDatasetDeleteLayer(self.cogr_ds, idx)
+                ogrext2.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_layer = ogrext2.GDALDatasetCreateLayer(
                 self.cogr_ds, 
                 name_c,
                 cogr_srs,
@@ -931,9 +931,9 @@ cdef class WritingSession(Session):
                 )
 
             if cogr_srs != NULL:
-                ograpi.OSRDestroySpatialReference(cogr_srs)
+                ogrext2.OSRDestroySpatialReference(cogr_srs)
             if options != NULL:
-                ograpi.CSLDestroy(options)
+                ogrext2.CSLDestroy(options)
 
             if self.cogr_layer == NULL:
                 raise ValueError("Null layer")
@@ -966,17 +966,17 @@ cdef class WritingSession(Session):
                 encoding = self.get_internalencoding()
                 key_bytes = key.encode(encoding)
 
-                cogr_fielddefn = ograpi.OGR_Fld_Create(
+                cogr_fielddefn = ogrext2.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)
+                    ogrext2.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)
+                    ogrext2.OGR_Fld_SetPrecision(cogr_fielddefn, precision)
+                ogrext2.OGR_L_CreateField(self.cogr_layer, cogr_fielddefn, 1)
+                ogrext2.OGR_Fld_Destroy(cogr_fielddefn)
             log.debug("Created fields")
 
         # Mapping of the Python collection schema to the munged 
@@ -998,11 +998,11 @@ cdef class WritingSession(Session):
             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":
+        cogr_driver = ogrext2.GDALGetDatasetDriver(self.cogr_ds)
+        if ogrext2.OGR_Dr_GetName(cogr_driver) == b"GeoJSON":
             def validate_geometry_type(rec):
                 return True
-        elif ograpi.OGR_Dr_GetName(cogr_driver) == b"ESRI Shapefile" \
+        elif ogrext2.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")
@@ -1033,7 +1033,7 @@ cdef class WritingSession(Session):
                          collection.schema['geometry'] ))
 
             cogr_feature = OGRFeatureBuilder().build(record, collection)
-            result = ograpi.OGR_L_CreateFeature(cogr_layer, cogr_feature)
+            result = ogrext2.OGR_L_CreateFeature(cogr_layer, cogr_feature)
             if result != OGRERR_NONE:
                 raise RuntimeError("Failed to write record: %s" % record)
             _deleteOgrFeature(cogr_feature)
@@ -1046,7 +1046,7 @@ cdef class WritingSession(Session):
             raise ValueError("Null data source")
         log.debug("Syncing OGR to disk")
 
-        ograpi.GDALFlushCache(cogr_ds)
+        ogrext2.GDALFlushCache(cogr_ds)
 
 
 cdef class Iterator:
@@ -1064,8 +1064,8 @@ cdef class Iterator:
     cdef fastindex
     cdef stepsign
 
-    def __init__(self, collection, 
-            start=None, stop=None, step=None, bbox=None, mask=None):
+    def __cinit__(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
@@ -1075,28 +1075,28 @@ cdef class Iterator:
         cdef void *cogr_layer = session.cogr_layer
         if cogr_layer == NULL:
             raise ValueError("Null layer")
-        ograpi.OGR_L_ResetReading(cogr_layer)
+        ogrext2.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(
+            ogrext2.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)
+            ogrext2.OGR_L_SetSpatialFilter(cogr_layer, cogr_geometry)
+            ogrext2.OGR_G_DestroyGeometry(cogr_geometry)
             
         else:
-            ograpi.OGR_L_SetSpatialFilter(
+            ogrext2.OGR_L_SetSpatialFilter(
                 cogr_layer, NULL)
         self.encoding = session.get_internalencoding()
 
-        self.fastindex = ograpi.OGR_L_TestCapability(
+        self.fastindex = ogrext2.OGR_L_TestCapability(
             session.cogr_layer, OLC_FASTSETNEXTBYINDEX)
 
-        ftcount = ograpi.OGR_L_GetFeatureCount(session.cogr_layer, 0)
+        ftcount = ogrext2.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(
@@ -1126,7 +1126,7 @@ cdef class Iterator:
 
         self.next_index = start
         log.debug("Index: %d", self.next_index)
-        ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
+        ogrext2.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
 
 
     def __iter__(self):
@@ -1153,22 +1153,22 @@ cdef class Iterator:
 
         # Set read cursor to next_item position
         if self.step > 1 and self.fastindex:
-            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
+            ogrext2.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)
+                cogr_feature = ogrext2.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)
+            ogrext2.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
 
         elif self.step == 0:
-            # ograpi.OGR_L_GetNextFeature increments read cursor by one
+            # ogrext2.OGR_L_GetNextFeature increments read cursor by one
             pass
         elif self.step < 0:
-            ograpi.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
+            ogrext2.OGR_L_SetNextByIndex(session.cogr_layer, self.next_index)
             
         # set the next index
         self.next_index += self.step
@@ -1183,7 +1183,7 @@ cdef class Iterator:
         self._next()
 
         # Get the next feature.
-        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
+        cogr_feature = ogrext2.OGR_L_GetNextFeature(session.cogr_layer)
         if cogr_feature == NULL:
             raise StopIteration
 
@@ -1210,12 +1210,12 @@ cdef class ItemsIterator(Iterator):
         self._next()
 
         # Get the next feature.
-        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
+        cogr_feature = ogrext2.OGR_L_GetNextFeature(session.cogr_layer)
         if cogr_feature == NULL:
             raise StopIteration
 
 
-        fid = ograpi.OGR_F_GetFID(cogr_feature)
+        fid = ogrext2.OGR_F_GetFID(cogr_feature)
         feature = FeatureBuilder().build(
             cogr_feature,
             bbox=False,
@@ -1239,11 +1239,11 @@ cdef class KeysIterator(Iterator):
         self._next()
 
         # Get the next feature.
-        cogr_feature = ograpi.OGR_L_GetNextFeature(session.cogr_layer)
+        cogr_feature = ogrext2.OGR_L_GetNextFeature(session.cogr_layer)
         if cogr_feature == NULL:
             raise StopIteration
 
-        fid = ograpi.OGR_F_GetFID(cogr_feature)
+        fid = ogrext2.OGR_F_GetFID(cogr_feature)
         _deleteOgrFeature(cogr_feature)
 
         return fid
@@ -1258,14 +1258,14 @@ def _remove(path, driver=None):
     if driver is None:
         driver = 'ESRI Shapefile'
 
-    cogr_driver = ograpi.OGRGetDriverByName(driver.encode('utf-8'))
+    cogr_driver = ogrext2.OGRGetDriverByName(driver.encode('utf-8'))
     if cogr_driver == NULL:
         raise ValueError("Null driver")
 
-    if not ograpi.OGR_Dr_TestCapability(cogr_driver, ODrCDeleteDataSource):
+    if not ogrext2.OGR_Dr_TestCapability(cogr_driver, ODrCDeleteDataSource):
         raise RuntimeError("Driver does not support dataset removal operation")
 
-    result = ograpi.GDALDeleteDataset(cogr_driver, path.encode('utf-8'))
+    result = ogrext2.GDALDeleteDataset(cogr_driver, path.encode('utf-8'))
     if result != OGRERR_NONE:
         raise RuntimeError("Failed to remove data source {}".format(path))
 
@@ -1287,27 +1287,27 @@ def _listlayers(path):
         path_b = path
     path_c = path_b
     with cpl_errs:
-        cogr_ds = ograpi.GDALOpenEx(path_c,
-             ograpi.GDAL_OF_VECTOR | ograpi.GDAL_OF_READONLY,
+        cogr_ds = ogrext2.GDALOpenEx(path_c,
+             ogrext2.GDAL_OF_VECTOR | ogrext2.GDAL_OF_READONLY,
              NULL,
              NULL,
              NULL)
-#         cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
+#         cogr_ds = ogrext2.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_count = ogrext2.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)
+        cogr_layer = ogrext2.GDALDatasetGetLayer(cogr_ds, i)
+        name_c = ogrext2.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)
+        ogrext2.GDALClose(cogr_ds)
     cogr_ds = NULL
 
     return layer_names
@@ -1318,16 +1318,16 @@ def buffer_to_virtual_file(bytesbuf):
     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)
+    vsi_handle = ogrext2.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:
+    if ogrext2.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)
+    return ogrext2.VSIUnlink(vsi_cfilename)
 
 
diff --git a/setup.py b/setup.py
index 53a9380..efee743 100644
--- a/setup.py
+++ b/setup.py
@@ -1,8 +1,10 @@
+from distutils.command.sdist import sdist
 import logging
 import os
 import shutil
 import subprocess
 import sys
+
 from setuptools import setup
 from setuptools.extension import Extension
 
@@ -12,6 +14,7 @@ try:
 except ImportError:
     cythonize = None
 
+
 logging.basicConfig()
 log = logging.getLogger()
 
@@ -19,6 +22,7 @@ log = logging.getLogger()
 if 'all' in sys.warnoptions:
     log.level = logging.DEBUG
 
+
 def check_output(cmd):
     # since subprocess.check_output doesn't exist in 2.6
     # we wrap it here.
@@ -32,6 +36,7 @@ def check_output(cmd):
         out, err = p.communicate()
         return out
 
+
 def copy_data_tree(datadir, destdir):
     try:
         shutil.rmtree(destdir)
@@ -66,22 +71,50 @@ with open('CREDITS.txt', **open_kwds) as f:
 with open('CHANGES.txt', **open_kwds) as f:
     changes = f.read()
 
+# Set a flag for builds where the source directory is a repo checkout.
+source_is_repo = os.path.exists("MANIFEST.in")
+
 
-def copy_gdalapi(gdalversion):
+def copy_gdalapi_pyx(gdalversion):
     if gdalversion[0] == u'1':
         log.info("Building Fiona for gdal 1.x: {0}".format(gdalversion))
         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: {0}".format(gdalversion))
         shutil.copy('fiona/ogrext2.pyx', 'fiona/ogrext.pyx')
-        shutil.copy('fiona/ograpi2.pxd', 'fiona/ograpi.pxd')
+
+
+def copy_gdalapi_c(gdalversion):
+    if gdalversion[0] == u'1':
+        log.info("Building Fiona for gdal 1.x: {0}".format(gdalversion))
+        shutil.copy('fiona/ogrext1.c', 'fiona/ogrext.c')
+        print("Copied 'fiona/ogrext1.c' to'fiona/ogrext.c'")
+    else:
+        log.info("Building Fiona for gdal 2.x: {0}".format(gdalversion))
+        shutil.copy('fiona/ogrext2.c', 'fiona/ogrext.c')
+        print("Copied 'fiona/ogrext2.c' to 'fiona/ogrext.c'")
+
 
 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)
-    copy_gdalapi(gdalversion)
+
+
+# Extend distutil's sdist command to generate C extension sources from
+# both `ogrext`.pyx` and `ogrext2.pyx` for GDAL 1.x and 2.x.
+class sdist_multi_gdal(sdist):
+    def run(self):
+        shutil.copy('fiona/ogrext1.pyx', 'fiona/ogrext.pyx')
+        _ = check_output(['cython', '-v', '-f', 'fiona/ogrext.pyx',
+                          '-o', 'fiona/ogrext1.c'])
+        print(_)
+        shutil.copy('fiona/ogrext2.pyx', 'fiona/ogrext.pyx')
+        _ = check_output(['cython', '-v', '-f', 'fiona/ogrext.pyx',
+                          '-o', 'fiona/ogrext2.c'])
+        print(_)
+        sdist.run(self)
+
 
 # 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.
@@ -94,7 +127,8 @@ gdal_output = [None] * 4
 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")):
+        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():
@@ -108,8 +142,7 @@ if 'clean' not in sys.argv:
             else:
                 # e.g. -framework GDAL
                 extra_link_args.append(item)
-
-        copy_gdalapi(gdal_output[3])
+        gdalversion = gdal_output[3]
 
     except Exception as e:
         if os.name == "nt":
@@ -144,7 +177,7 @@ ext_options = dict(
     extra_link_args=extra_link_args)
 
 # When building from a repo, Cython is required.
-if os.path.exists("MANIFEST.in") and "clean" not in sys.argv:
+if source_is_repo and "clean" not in sys.argv:
     log.info("MANIFEST.in found, presume a repo, cythonizing...")
     if not cythonize:
         log.critical(
@@ -152,6 +185,7 @@ if os.path.exists("MANIFEST.in") and "clean" not in sys.argv:
             "Cython is required to build from a repo.")
         sys.exit(1)
 
+    copy_gdalapi_pyx(gdalversion)
     ext_modules = cythonize([
         Extension('fiona._geometry', ['fiona/_geometry.pyx'], **ext_options),
         Extension('fiona._transform', ['fiona/_transform.pyx'], **ext_options),
@@ -161,6 +195,7 @@ if os.path.exists("MANIFEST.in") and "clean" not in sys.argv:
         Extension('fiona.ogrext', ['fiona/ogrext.pyx'], **ext_options)])
 # If there's no manifest template, as in an sdist, we just specify .c files.
 else:
+    copy_gdalapi_c(gdalversion)
     ext_modules = [
         Extension('fiona._transform', ['fiona/_transform.cpp'], **ext_options),
         Extension('fiona._geometry', ['fiona/_geometry.c'], **ext_options),
@@ -180,6 +215,7 @@ if sys.version_info < (2, 7):
     requirements.append('ordereddict')
 
 setup_args = dict(
+    cmdclass={'sdist': sdist_multi_gdal},
     metadata_version='1.2',
     name='Fiona',
     version=version,
@@ -229,8 +265,7 @@ setup_args = dict(
         'Operating System :: OS Independent',
         'Programming Language :: Python :: 2',
         'Programming Language :: Python :: 3',
-        'Topic :: Scientific/Engineering :: GIS',
-    ])
+        'Topic :: Scientific/Engineering :: GIS'])
 
 if os.environ.get('PACKAGE_DATA'):
     setup_args['package_data'] = {'fiona': ['gdal_data/*', 'proj_data/*']}
diff --git a/tests/test_bytescollection.py b/tests/test_bytescollection.py
index cdee1f0..9318f61 100644
--- a/tests/test_bytescollection.py
+++ b/tests/test_bytescollection.py
@@ -1,10 +1,13 @@
 # Testing BytesCollection
+import sys
 import unittest
 
 import six
 
 import fiona
 
+FIXME_WINDOWS = sys.platform.startswith('win')
+
 class ReadingTest(unittest.TestCase):
 
     def setUp(self):
@@ -21,18 +24,20 @@ class ReadingTest(unittest.TestCase):
             strbuf = src.read()
         self.assertRaises(ValueError, fiona.BytesCollection, strbuf)
 
+    @unittest.skipIf(FIXME_WINDOWS, 
+                     reason="FIXME on Windows. Please look into why this test is not working.")
     def test_open_repr(self):
         # I'm skipping checking the name of the virtual file as it produced by uuid.
-        self.assertTrue(
-            repr(self.c).startswith("<open BytesCollection '/vsimem/") and
-            repr(self.c).endswith(":OGRGeoJSON', mode 'r' at %s>" % hex(id(self.c))))
+        self.assertTrue(repr(self.c).startswith("<open BytesCollection '/vsimem/"))
+        self.assertTrue(repr(self.c).endswith(":OGRGeoJSON', mode 'r' at %s>" % hex(id(self.c))))
 
+    @unittest.skipIf(FIXME_WINDOWS, 
+                     reason="FIXME on Windows. Please look into why this test is not working.")
     def test_closed_repr(self):
         # I'm skipping checking the name of the virtual file as it produced by uuid.
         self.c.close()
-        self.assertTrue(
-            repr(self.c).startswith("<closed BytesCollection '/vsimem/") and
-            repr(self.c).endswith(":OGRGeoJSON', mode 'r' at %s>" % hex(id(self.c))))
+        self.assertTrue(repr(self.c).startswith("<closed BytesCollection '/vsimem/"))
+        self.assertTrue(repr(self.c).endswith(":OGRGeoJSON', mode 'r' at %s>" % hex(id(self.c))))
 
     def test_path(self):
         self.assertEqual(self.c.path, self.c.virtual_file)
@@ -51,6 +56,8 @@ class ReadingTest(unittest.TestCase):
     def test_mode(self):
         self.assertEqual(self.c.mode, 'r')
 
+    @unittest.skipIf(FIXME_WINDOWS, 
+                     reason="FIXME on Windows. Please look into why this test is not working.")
     def test_collection(self):
         self.assertEqual(self.c.encoding, 'utf-8')
 
diff --git a/tests/test_collection.py b/tests/test_collection.py
index 8c9cbd9..d4da794 100644
--- a/tests/test_collection.py
+++ b/tests/test_collection.py
@@ -1,18 +1,19 @@
 # Testing collections and workspaces
 
+import datetime
 import logging
 import os
 import shutil
 import sys
 import subprocess
-import unittest
 import tempfile
-import datetime
+import unittest
 
 import fiona
 from fiona.collection import Collection, supported_drivers
 from fiona.errors import FionaValueError, DriverError, SchemaError, CRSError
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
 WILDSHP = 'tests/data/coutwildrnp.shp'
 
@@ -309,10 +310,12 @@ class UnsupportedDriverTest(unittest.TestCase):
             DriverError,
             fiona.open, os.path.join(TEMPDIR, "foo"), "w", "Bogus", schema=schema)
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test isn't working. There is a codepage issue regarding Windows-1252 and UTF-8. ")
 class GenericWritingTest(unittest.TestCase):
 
-    def setUp(self):
+    @classmethod
+    def setUpClass(self):
         self.tempdir = tempfile.mkdtemp()
         schema = {
             'geometry': 'Point',
@@ -321,12 +324,13 @@ class GenericWritingTest(unittest.TestCase):
                             'w', driver="ESRI Shapefile", schema=schema,
                             encoding='Windows-1252')
 
-    def tearDown(self):
+    @classmethod
+    def tearDownClass(self):
         self.c.close()
         shutil.rmtree(self.tempdir)
 
     def test_encoding(self):
-        self.assertEquals(self.c.encoding, 'Windows-1252')
+        self.assertEqual(self.c.encoding, 'Windows-1252')
 
     def test_no_iter(self):
         self.assertRaises(IOError, iter, self.c)
@@ -372,7 +376,7 @@ class PointWritingTest(unittest.TestCase):
         self.sink.close()
         info = subprocess.check_output(
             ["ogrinfo", self.filename, "point_writing_test"])
-        self.assert_(
+        self.assertTrue(
             'date (Date) = 2012/01/29' in info.decode('utf-8'),
             info)
 
@@ -566,6 +570,8 @@ class CollectionTest(unittest.TestCase):
     def test_no_read_conn_str(self):
         self.assertRaises(IOError, fiona.open, "PG:dbname=databasename", "r")
 
+    @unittest.skipIf(sys.platform.startswith("win"),
+                     reason="test only for *nix based system")
     def test_no_read_directory(self):
         self.assertRaises(ValueError, fiona.open, "/dev/null", "r")
 
@@ -583,6 +589,7 @@ class GeoJSONCRSWritingTest(unittest.TestCase):
                 'geometry': 'Point',
                 'properties': [('title', 'str'), ('date', 'date')]},
             crs={'a': 6370997, 'lon_0': -100, 'y_0': 0, 'no_defs': True, 'proj': 'laea', 'x_0': 0, 'units': 'm', 'b': 6370997, 'lat_0': 45})
+        
 
     def tearDown(self):
         self.sink.close()
@@ -593,11 +600,12 @@ class GeoJSONCRSWritingTest(unittest.TestCase):
         self.sink.close()
         info = subprocess.check_output(
             ["ogrinfo", self.filename, "OGRGeoJSON"])
-        self.assert_(
+        self.assertTrue(
             'GEOGCS["WGS 84' in info.decode('utf-8'),
             info)
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Test raises PermissionError.  Please look into why this test isn't working.")
 class DateTimeTest(unittest.TestCase):
 
     def setUp(self):
@@ -626,12 +634,13 @@ class DateTimeTest(unittest.TestCase):
         self.sink.close()
         self.assertEqual(len(self.sink), 2)
 
-        c = fiona.open(os.path.join(self.tempdir, "date_test.shp"), "r")
-        self.assertEqual(len(c), 2)
+        with fiona.open(os.path.join(self.tempdir, "date_test.shp"), "r") as c:
+            self.assertEqual(len(c), 2)
 
-        rf1, rf2 = list(c)
-        self.assertEqual(rf1['properties']['date'], '2013-02-25')
-        self.assertEqual(rf2['properties']['date'], '2014-02-03')
+            rf1, rf2 = list(c)
+            self.assertEqual(rf1['properties']['date'], '2013-02-25')
+            self.assertEqual(rf2['properties']['date'], '2014-02-03')
+        
 
     def tearDown(self):
         shutil.rmtree(self.tempdir)
diff --git a/tests/test_drivers.py b/tests/test_drivers.py
index 18ef430..9d88aa9 100644
--- a/tests/test_drivers.py
+++ b/tests/test_drivers.py
@@ -3,12 +3,17 @@ import os.path
 import shutil
 import sys
 import tempfile
+import unittest
 
 import fiona
 
 
 logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
+FIXME_WINDOWS = sys.platform.startswith('win')
+
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Raises PermissionError Please look into why this test isn't working.")
 def test_options(tmpdir=None):
     """Test that setting CPL_DEBUG=ON works"""
     if tmpdir is None:
diff --git a/tests/test_fio_cat.py b/tests/test_fio_cat.py
index f203bc5..04f6cdd 100644
--- a/tests/test_fio_cat.py
+++ b/tests/test_fio_cat.py
@@ -1,4 +1,6 @@
 import json
+import sys
+import unittest
 
 from click.testing import CliRunner
 
@@ -10,21 +12,26 @@ from .fixtures import feature_seq_pp_rs
 
 WILDSHP = 'tests/data/coutwildrnp.shp'
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_one():
     runner = CliRunner()
     result = runner.invoke(cat.cat, [WILDSHP])
     assert result.exit_code == 0
     assert result.output.count('"Feature"') == 67
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_two():
     runner = CliRunner()
     result = runner.invoke(cat.cat, [WILDSHP, WILDSHP])
     assert result.exit_code == 0
     assert result.output.count('"Feature"') == 134
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_bbox_no():
     runner = CliRunner()
     result = runner.invoke(
@@ -34,7 +41,8 @@ def test_bbox_no():
     assert result.exit_code == 0
     assert result.output == ""
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_bbox_yes():
     runner = CliRunner()
     result = runner.invoke(
@@ -44,7 +52,8 @@ def test_bbox_yes():
     assert result.exit_code == 0
     assert result.output.count('"Feature"') == 19
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_bbox_json_yes():
     runner = CliRunner()
     result = runner.invoke(
@@ -53,3 +62,19 @@ def test_bbox_json_yes():
         catch_exceptions=False)
     assert result.exit_code == 0
     assert result.output.count('"Feature"') == 19
+
+
+def test_multi_layer():
+    layerdef = "1:coutwildrnp,1:coutwildrnp"
+    runner = CliRunner()
+    result = runner.invoke(
+        cat.cat, ['--layer', layerdef, 'tests/data/'])
+    assert result.output.count('"Feature"') == 134
+
+
+def test_multi_layer_fail():
+    runner = CliRunner()
+    result = runner.invoke(cat.cat, '--layer'
+                           '200000:coutlildrnp',
+                           'tests/data')
+    assert result.exit_code == 1
diff --git a/tests/test_fio_collect.py b/tests/test_fio_collect.py
index b1a2e4c..2e346be 100644
--- a/tests/test_fio_collect.py
+++ b/tests/test_fio_collect.py
@@ -2,6 +2,8 @@
 
 
 import json
+import sys
+import unittest
 
 from click.testing import CliRunner
 
@@ -10,7 +12,10 @@ from fiona.fio import collect
 from .fixtures import feature_seq
 from .fixtures import feature_seq_pp_rs
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_collect_rs():
     runner = CliRunner()
     result = runner.invoke(
@@ -22,6 +27,8 @@ def test_collect_rs():
     assert result.output.count('"Feature"') == 2
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_collect_no_rs():
     runner = CliRunner()
     result = runner.invoke(
diff --git a/tests/test_fio_dump.py b/tests/test_fio_dump.py
index 8efc3b8..165b5a6 100644
--- a/tests/test_fio_dump.py
+++ b/tests/test_fio_dump.py
@@ -1,5 +1,7 @@
 """Unittests for $ fio dump"""
 
+import sys
+import unittest
 
 from click.testing import CliRunner
 
@@ -7,10 +9,22 @@ from fiona.fio import dump
 
 
 WILDSHP = 'tests/data/coutwildrnp.shp'
+TESTGPX = 'tests/data/test_gpx.gpx'
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_dump():
     runner = CliRunner()
     result = runner.invoke(dump.dump, [WILDSHP])
     assert result.exit_code == 0
     assert '"FeatureCollection"' in result.output
+
+
+def test_dump_layer():
+    for layer in ('routes', '1'):
+        runner = CliRunner()
+        result = runner.invoke(dump.dump, [TESTGPX, '--layer', layer])
+        assert result.exit_code == 0
+        assert '"FeatureCollection"' in result.output
diff --git a/tests/test_fio_info.py b/tests/test_fio_info.py
index c36622f..548ae55 100644
--- a/tests/test_fio_info.py
+++ b/tests/test_fio_info.py
@@ -1,6 +1,8 @@
 import json
 from pkg_resources import iter_entry_points
 import re
+import sys
+import unittest
 
 from click.testing import CliRunner
 
@@ -9,7 +11,10 @@ from fiona.fio.main import main_group
 
 WILDSHP = 'tests/data/coutwildrnp.shp'
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_info_json():
     runner = CliRunner()
     result = runner.invoke(main_group, ['info', WILDSHP])
@@ -19,14 +24,16 @@ def test_info_json():
     assert '"driver": "ESRI Shapefile"' in result.output
     assert '"name": "coutwildrnp"' in result.output
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_info_count():
     runner = CliRunner()
     result = runner.invoke(main_group, ['info', '--count', WILDSHP])
     assert result.exit_code == 0
     assert result.output == "67\n"
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_info_bounds():
     runner = CliRunner()
     result = runner.invoke(main_group, ['info', '--bounds', WILDSHP])
@@ -47,6 +54,8 @@ def _filter_info_warning(lines):
     return lines
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_info_no_count():
     """Make sure we can still get a `$ fio info` report on datasources that do
     not support feature counting, AKA `len(collection)`.
@@ -59,6 +68,8 @@ def test_info_no_count():
     assert json.loads(lines[0])['count'] is None
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_info_layer():
     for layer in ('routes', '1'):
         runner = CliRunner()
diff --git a/tests/test_fio_load.py b/tests/test_fio_load.py
index fce5f08..c5a19b3 100644
--- a/tests/test_fio_load.py
+++ b/tests/test_fio_load.py
@@ -1,7 +1,9 @@
 import json
 import os
 import shutil
+import sys
 import tempfile
+import unittest
 
 from click.testing import CliRunner
 
@@ -11,6 +13,7 @@ from fiona.fio.main import main_group
 from .fixtures import (
     feature_collection, feature_seq, feature_seq_pp_rs)
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
 def test_err():
     runner = CliRunner()
@@ -30,7 +33,8 @@ def test_exception(tmpdir=None):
         main_group, ['load', '-f', 'Shapefile', tmpfile], '42', catch_exceptions=False)
     assert result.exit_code == 1
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_collection(tmpdir=None):
     if tmpdir is None:
         tmpdir = tempfile.mkdtemp()
@@ -44,6 +48,8 @@ def test_collection(tmpdir=None):
     assert len(fiona.open(tmpfile)) == 2
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_seq_rs(tmpdir=None):
     if tmpdir is None:
         tmpdir = tempfile.mkdtemp()
@@ -57,6 +63,8 @@ def test_seq_rs(tmpdir=None):
     assert len(fiona.open(tmpfile)) == 2
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_seq_no_rs(tmpdir=None):
     if tmpdir is None:
         tmpdir = tempfile.mkdtemp()
@@ -70,6 +78,8 @@ def test_seq_no_rs(tmpdir=None):
     assert len(fiona.open(tmpfile)) == 2
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_dst_crs_default_to_src_crs(tmpdir=None):
     # When --dst-crs is not given default to --src-crs.
     if tmpdir is None:
@@ -88,6 +98,8 @@ def test_dst_crs_default_to_src_crs(tmpdir=None):
         assert len(src) == len(feature_seq.splitlines())
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_different_crs(tmpdir=None):
     if tmpdir is None:
         tmpdir = tempfile.mkdtemp()
@@ -106,6 +118,8 @@ def test_different_crs(tmpdir=None):
         assert len(src) == len(feature_seq.splitlines())
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_dst_crs_no_src(tmpdir=None):
     if tmpdir is None:
         tmpdir = tempfile.mkdtemp()
@@ -123,6 +137,8 @@ def test_dst_crs_no_src(tmpdir=None):
         assert len(src) == len(feature_seq.splitlines())
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_fio_load_layer():
 
     tmpdir = tempfile.mkdtemp()
diff --git a/tests/test_fio_ls.py b/tests/test_fio_ls.py
index d8be2b1..4ea80b5 100644
--- a/tests/test_fio_ls.py
+++ b/tests/test_fio_ls.py
@@ -3,14 +3,19 @@
 
 import json
 import shutil
+import sys
 import tempfile
+import unittest
 
 from click.testing import CliRunner
 
 import fiona
 from fiona.fio.main import main_group
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_fio_ls_single_layer():
 
     result = CliRunner().invoke(main_group, [
@@ -21,6 +26,8 @@ def test_fio_ls_single_layer():
     assert json.loads(result.output) == ['coutwildrnp']
 
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why this test is not working.")
 def test_fio_ls_indent():
 
     result = CliRunner().invoke(main_group, [
diff --git a/tests/test_geojson.py b/tests/test_geojson.py
index 79b41c8..e6c26c2 100644
--- a/tests/test_geojson.py
+++ b/tests/test_geojson.py
@@ -22,7 +22,7 @@ class ReadingTest(unittest.TestCase):
         self.c.close()
 
     def test_json(self):
-        self.assertEquals(len(self.c), 67)
+        self.assertEqual(len(self.c), 67)
 
 class WritingTest(unittest.TestCase):
 
@@ -44,5 +44,5 @@ class WritingTest(unittest.TestCase):
                 'geometry': {'type': 'MultiPoint', 'coordinates': [[0.0, 0.0]]},
                 'properties': {'title': 'Two'}}])
         with fiona.open(path) as c:
-            self.assertEquals(c.schema['geometry'], 'Unknown')
-            self.assertEquals(len(c), 2)
+            self.assertEqual(c.schema['geometry'], 'Unknown')
+            self.assertEqual(len(c), 2)
diff --git a/tests/test_listing.py b/tests/test_listing.py
index 9e4d2c8..d9b29aa 100644
--- a/tests/test_listing.py
+++ b/tests/test_listing.py
@@ -7,6 +7,8 @@ import unittest
 import fiona
 import fiona.ogrext
 
+FIXME_WINDOWS = sys.platform.startswith("win")
+
 logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
 def test_single_file_private():
@@ -19,6 +21,8 @@ def test_single_file():
 def test_directory():
     assert fiona.listlayers('tests/data') == ['coutwildrnp']
 
+ at unittest.skipIf(FIXME_WINDOWS,
+                 reason="FIXME on Windows. ValueError raised. Please look into why this test isn't working.")
 def test_directory_trailing_slash():
     assert fiona.listlayers('tests/data/') == ['coutwildrnp']
 
diff --git a/tests/test_multiconxn.py b/tests/test_multiconxn.py
index 2fed3e5..485800c 100644
--- a/tests/test_multiconxn.py
+++ b/tests/test_multiconxn.py
@@ -10,6 +10,8 @@ from fiona.odict import OrderedDict
 
 logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
+FIXME_WINDOWS = sys.platform.startswith("win")
+
 class ReadAccess(unittest.TestCase):
     # To check that we'll be able to get multiple 'r' connections to layers
     # in a single file.
@@ -31,6 +33,8 @@ class ReadAccess(unittest.TestCase):
             f2 = next(c2)
             self.assertEqual(f1, f2)
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. These tests raise PermissionErrors on Windows in Python 3.x (which doesn't exist in Python 2.7).  Please look into why this test isn't working.")
 class ReadWriteAccess(unittest.TestCase):
     # To check that we'll be able to read from a file that we're
     # writing to.
@@ -75,6 +79,8 @@ class ReadWriteAccess(unittest.TestCase):
         del f2['id']
         self.assertEqual(self.f, f2)
 
+ at unittest.skipIf(FIXME_WINDOWS, 
+                    reason="FIXME on Windows. These tests raise PermissionErrors on Windows in Python 3.x (which doesn't exist in Python 2.7).  Please look into why this test isn't working.")
 class LayerCreation(unittest.TestCase):
 
     def setUp(self):
diff --git a/tests/test_non_counting_layer.py b/tests/test_non_counting_layer.py
index f33f4db..46632d3 100644
--- a/tests/test_non_counting_layer.py
+++ b/tests/test_non_counting_layer.py
@@ -17,7 +17,7 @@ class NonCountingLayerTest(unittest.TestCase):
 
     def test_list(self):
         features = list(self.c)
-        self.assertEquals(len(features), 19)
+        self.assertEqual(len(features), 19)
 
     def test_getitem(self):
         feature = self.c[2]
@@ -28,7 +28,7 @@ class NonCountingLayerTest(unittest.TestCase):
 
     def test_slice(self):
         features = self.c[2:5]
-        self.assertEquals(len(features), 3)
+        self.assertEqual(len(features), 3)
 
     def test_fail_slice_negative_index(self):
         with self.assertRaises(IndexError):
diff --git a/tests/test_unicode.py b/tests/test_unicode.py
index 6def0d3..70e7a1c 100644
--- a/tests/test_unicode.py
+++ b/tests/test_unicode.py
@@ -15,6 +15,7 @@ import fiona
 
 logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
+FIXME_WINDOWS = sys.platform.startswith('win')
 
 class UnicodePathTest(unittest.TestCase):
 
@@ -48,7 +49,8 @@ class UnicodePathTest(unittest.TestCase):
             with fiona.open(path) as c:
                 assert len(c) == 67
 
-
+ at unittest.skipIf(FIXME_WINDOWS, 
+                 reason="FIXME on Windows. Please look into why these tests are not working. Note: test_write_utf8 works.")
 class UnicodeStringFieldTest(unittest.TestCase):
 
     def setUp(self):
@@ -88,7 +90,7 @@ class UnicodeStringFieldTest(unittest.TestCase):
         with fiona.open(os.path.join(self.tempdir), encoding='latin1') as c:
             f = next(c)
             # Next assert fails.
-            self.assertEquals(f['properties']['label'], u'徐汇区')
+            self.assertEqual(f['properties']['label'], u'徐汇区')
 
     def test_write_utf8(self):
         schema = {
@@ -105,8 +107,8 @@ class UnicodeStringFieldTest(unittest.TestCase):
 
         with fiona.open(os.path.join(self.tempdir), encoding='utf-8') as c:
             f = next(c)
-            self.assertEquals(f['properties']['label'], u'Ba\u2019kelalan')
-            self.assertEquals(f['properties'][u'verit\xe9'], 0)
+            self.assertEqual(f['properties']['label'], u'Ba\u2019kelalan')
+            self.assertEqual(f['properties'][u'verit\xe9'], 0)
 
     def test_write_gb18030(self):
         """Can write a simplified Chinese shapefile"""
@@ -123,5 +125,5 @@ class UnicodeStringFieldTest(unittest.TestCase):
 
         with fiona.open(os.path.join(self.tempdir), encoding='gb18030') as c:
             f = next(c)
-            self.assertEquals(f['properties']['label'], u'徐汇区')
-            self.assertEquals(f['properties']['num'], 0)
+            self.assertEqual(f['properties']['label'], u'徐汇区')
+            self.assertEqual(f['properties']['num'], 0)

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