[fiona] 01/01: Imported Upstream version 1.5.0

Johan Van de Wauw johanvdw-guest at moszumanska.debian.org
Wed Feb 4 16:13:43 UTC 2015


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

johanvdw-guest pushed a commit to branch upstream
in repository fiona.

commit 5263767c049f1c580c12e6924fca7e0961af61ab
Author: Johan Van de Wauw <johan.vandewauw at gmail.com>
Date:   Wed Feb 4 17:12:41 2015 +0100

    Imported Upstream version 1.5.0
---
 .travis.yml                                        |   8 +-
 CHANGES.txt                                        |  12 +
 CREDITS.txt                                        |   1 +
 README.rst                                         |   3 +
 docs/data/test_uk.dbf                              | Bin 10129 -> 0 bytes
 docs/data/test_uk.gpkg                             | Bin 86016 -> 0 bytes
 docs/data/test_uk.shp                              | Bin 65156 -> 0 bytes
 docs/data/test_uk.shx                              | Bin 484 -> 0 bytes
 fiona/__init__.py                                  |  36 +-
 fiona/_drivers.pyx                                 | 236 +++++++-
 fiona/collection.py                                | 147 +----
 fiona/errors.py                                    |   3 +
 fiona/fio/bounds.py                                |  20 +-
 fiona/fio/cat.py                                   |  96 +---
 fiona/fio/cli.py                                   |   5 +-
 fiona/fio/fio.py                                   |  35 +-
 fiona/ograpi.pxd                                   |   3 +-
 fiona/ogrext.pyx                                   |  72 +--
 requirements.txt                                   |   2 +-
 setup.py                                           |  49 +-
 tests/__init__.py                                  |  10 +-
 tests/data/LICENSE.txt                             |   4 +
 tests/data/collection-pp.txt                       | 635 +++++++++++++++++++++
 tests/data/collection.txt                          |   1 +
 tests/data/coutwildrnp.dbf                         | Bin 0 -> 43233 bytes
 .../data/test_uk.prj => tests/data/coutwildrnp.prj |   0
 tests/data/coutwildrnp.shp                         | Bin 0 -> 109548 bytes
 tests/data/coutwildrnp.shx                         | Bin 0 -> 636 bytes
 tests/data/sequence-pp.txt                         | 630 ++++++++++++++++++++
 tests/data/sequence.txt                            |   2 +
 tests/data/test_gpx.gpx                            |  34 ++
 tests/fixtures.py                                  |  10 +
 tests/test_bounds.py                               |  28 +-
 tests/test_cli.py                                  |  91 +--
 tests/test_collection.py                           | 116 ++--
 tests/test_drivers.py                              |   6 +-
 tests/test_fio_bounds.py                           |  97 ++--
 tests/test_fio_cat.py                              |  63 +-
 tests/test_fio_load.py                             |  70 +++
 tests/test_geojson.py                              |   4 +-
 tests/test_geopackage.py                           |   8 +-
 tests/test_layer.py                                |  24 +-
 tests/test_listing.py                              |  12 +-
 tests/test_multiconxn.py                           |   7 +-
 tests/test_non_counting_layer.py                   |  35 ++
 tests/test_read_drivers.py                         |  26 +
 tests/test_revolvingdoor.py                        |   3 +-
 tests/test_slice.py                                |  12 +-
 tests/test_unicode.py                              |  15 +-
 tests/test_vfs.py                                  |  30 +-
 50 files changed, 2136 insertions(+), 565 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index a97c839..a126e9d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,5 +9,11 @@ before_install:
   - sudo apt-get install -y libgdal1h gdal-bin libgdal-dev
 install:
   - "pip install -r requirements-dev.txt"
+  - "pip install pytest"
+  - "pip install coveralls"
   - "pip install -e ."
-script: nosetests --exclude test_filter_vsi
+script: 
+  - nosetests --exclude test_filter_vsi --exclude test_geopackage
+  - coverage run --source=fiona --omit='*.pxd,*.pyx,*/tests/*,*/docs/*,*/examples/*,*/benchmarks/*' -m nose --exclude test_filter_vsi --exclude test_geopackage
+after_success:
+  - coveralls
diff --git a/CHANGES.txt b/CHANGES.txt
index 0b5bb86..6099533 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,18 @@
 Changes
 =======
 
+1.5.0 (2015-02-02)
+------------------
+- Finalize GeoJSON feature sequence options (#174).
+- Fix for reading of datasets that don't support feature counting (#190).
+- New test dataset (#188).
+- Fix for encoding error (#191).
+- Remove confusing warning (#195).
+- Add data files for binary wheels (#196).
+- Add control over drivers enabled when reading datasets (#203).
+- Use cligj for CLI options involving GeoJSON (#204).
+- Fix fio-info --bounds help (#206).
+
 1.4.8 (2014-11-02)
 ------------------
 - Add missing crs_wkt property as in Rasterio (#182).
diff --git a/CREDITS.txt b/CREDITS.txt
index 1d70bf1..4fcf276 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -22,6 +22,7 @@ With contributions by:
 * Brendan Wards (https://github.com/brendan-ward)
 * Michael Weisman (https://github.com/mweisman)
 * Andy Wilson (https://github.com/wilsaj)
+* Martijn Visser (https://github.com/visr)
 
 Fiona would not be possible without the great work of Frank Warmerdam and other
 GDAL/OGR developers.
diff --git a/README.rst b/README.rst
index 6690d32..bfebc1b 100644
--- a/README.rst
+++ b/README.rst
@@ -7,6 +7,9 @@ Fiona is OGR's neat, nimble, no-nonsense API for Python programmers.
 .. image:: https://travis-ci.org/Toblerity/Fiona.png?branch=master   
    :target: https://travis-ci.org/Toblerity/Fiona
 
+.. image:: https://coveralls.io/repos/Toblerity/Fiona/badge.png
+   :target: https://coveralls.io/r/Toblerity/Fiona
+
 Fiona is designed to be simple and dependable. It focuses on reading and
 writing data in standard Python IO style and relies upon familiar Python types
 and protocols such as files, dictionaries, mappings, and iterators instead of
diff --git a/docs/data/test_uk.dbf b/docs/data/test_uk.dbf
deleted file mode 100644
index 82e8484..0000000
Binary files a/docs/data/test_uk.dbf and /dev/null differ
diff --git a/docs/data/test_uk.gpkg b/docs/data/test_uk.gpkg
deleted file mode 100644
index f732f47..0000000
Binary files a/docs/data/test_uk.gpkg and /dev/null differ
diff --git a/docs/data/test_uk.shp b/docs/data/test_uk.shp
deleted file mode 100644
index cbd42b6..0000000
Binary files a/docs/data/test_uk.shp and /dev/null differ
diff --git a/docs/data/test_uk.shx b/docs/data/test_uk.shx
deleted file mode 100644
index fd2b15d..0000000
Binary files a/docs/data/test_uk.shx and /dev/null differ
diff --git a/fiona/__init__.py b/fiona/__init__.py
index 2bd2552..7e2f17a 100644
--- a/fiona/__init__.py
+++ b/fiona/__init__.py
@@ -63,14 +63,14 @@ writing modes) flush contents to disk when their ``with`` blocks end.
 """
 
 __all__ = ['bounds', 'listlayers', 'open', 'prop_type', 'prop_width']
-__version__ = "1.4.8"
+__version__ = "1.5.0"
 
 import logging
 import os
 from six import string_types
 
-from fiona.collection import Collection, supported_drivers, vsi_path
-from fiona._drivers import driver_count, GDALEnv
+from fiona.collection import Collection, vsi_path
+from fiona._drivers import driver_count, GDALEnv, supported_drivers
 from fiona.odict import OrderedDict
 from fiona.ogrext import _bounds, _listlayers, FIELD_TYPES_MAP
 
@@ -90,7 +90,8 @@ def open(
         crs=None,
         encoding=None,
         layer=None,
-        vfs=None ):
+        vfs=None,
+        enabled_drivers=None):
     
     """Open file at ``path`` in ``mode`` "r" (read), "a" (append), or
     "w" (write) and return a ``Collection`` object.
@@ -126,6 +127,19 @@ def open(
     "tar://"". In this case, the ``path`` must be an absolute path
     within that container.
 
+    The drivers enabled for opening datasets may be restricted to those
+    listed in the ``enabled_drivers`` parameter. This and the ``driver``
+    parameter afford much control over opening of files.
+
+      # Trying only the GeoJSON driver when opening to read, the
+      # following raises ``DataIOError``:
+      fiona.open('example.shp', driver='GeoJSON')
+
+      # Trying first the GeoJSON driver, then the Shapefile driver,
+      # the following succeeds:
+      fiona.open(
+          'example.shp', enabled_drivers=['GeoJSON', 'ESRI Shapefile'])
+
     """
     # Parse the vfs into a vsi and an archive path.
     path, vsi, archive = parse_paths(path, vfs)
@@ -135,8 +149,9 @@ def open(
                 raise IOError("no such archive file: %r" % archive)
         elif path != '-' and not os.path.exists(path):
             raise IOError("no such file or directory: %r" % path)
-        c = Collection(path, mode, 
-                encoding=encoding, layer=layer, vsi=vsi, archive=archive)
+        c = Collection(path, mode, driver=driver,
+                encoding=encoding, layer=layer, vsi=vsi, archive=archive,
+                enabled_drivers=enabled_drivers)
     elif mode == 'w':
         if schema:
             # Make an ordered dict of schema properties.
@@ -146,7 +161,8 @@ def open(
             this_schema = None
         c = Collection(path, mode, 
                 crs=crs, driver=driver, schema=this_schema, 
-                encoding=encoding, layer=layer, vsi=vsi, archive=archive)
+                encoding=encoding, layer=layer, vsi=vsi, archive=archive,
+                enabled_drivers=enabled_drivers)
     else:
         raise ValueError(
             "mode string must be one of 'r', 'w', or 'a', not %s" % mode)
@@ -220,14 +236,16 @@ def prop_type(text):
     key = text.split(':')[0]
     return FIELD_TYPES_MAP[key]
 
+
 def drivers(*args, **kwargs):
     """Returns a context manager with registered drivers."""
     if driver_count == 0:
         log.debug("Creating a chief GDALEnv in drivers()")
-        return GDALEnv(True, **kwargs)
+        return GDALEnv(**kwargs)
     else:
         log.debug("Creating a not-responsible GDALEnv in drivers()")
-        return GDALEnv(False, **kwargs)
+        return GDALEnv(**kwargs)
+
 
 def bounds(ob):
     """Returns a (minx, miny, maxx, maxy) bounding box.
diff --git a/fiona/_drivers.pyx b/fiona/_drivers.pyx
index fbba3b8..604ce22 100644
--- a/fiona/_drivers.pyx
+++ b/fiona/_drivers.pyx
@@ -1,30 +1,43 @@
 # The GDAL and OGR driver registry.
 # GDAL driver management.
 
+import os
+import os.path
 import logging
+import sys
 
 from six import string_types
 
+
 cdef extern from "cpl_conv.h":
     void    CPLFree (void *ptr)
     void    CPLSetThreadLocalConfigOption (char *key, char *val)
     const char * CPLGetConfigOption ( const char *key, const char *default)
 
+
 cdef extern from "cpl_error.h":
-    void    CPLSetErrorHandler (void *handler)
+    void CPLSetErrorHandler (void *handler)
+
 
 cdef extern from "gdal.h":
     void GDALAllRegister()
     void GDALDestroyDriverManager()
     int GDALGetDriverCount()
+    void * GDALGetDriver(int i)
+    const char * GDALGetDriverShortName(void *driver)
+    const char * GDALGetDriverLongName(void *driver)
 
 
 cdef extern from "ogr_api.h":
+    void OGRRegisterDriver(void *driver)
+    void OGRDeregisterDriver(void *driver)
     void OGRRegisterAll()
     void OGRCleanupAll()
     int OGRGetDriverCount()
     void * OGRGetDriver(int i)
-    void * OGRGetDriverByName(const char *pszName)
+    void * OGRGetDriverByName(const char *name)
+    const char * OGR_Dr_GetName(void *driver)
+
 
 log = logging.getLogger('Fiona')
 class NullHandler(logging.Handler):
@@ -32,38 +45,75 @@ class NullHandler(logging.Handler):
         pass
 log.addHandler(NullHandler())
 
-code_map = {
-    0: 0, 
-    1: logging.DEBUG, 
-    2: logging.WARNING, 
-    3: logging.ERROR, 
+
+level_map = {
+    0: 0,
+    1: logging.DEBUG,
+    2: logging.WARNING,
+    3: logging.ERROR,
     4: logging.CRITICAL }
 
+code_map = {
+    0: 'CPLE_None',
+    1: 'CPLE_AppDefined',
+    2: 'CPLE_OutOfMemory',
+    3: 'CPLE_FileIO',
+    4: 'CPLE_OpenFailed',
+    5: 'CPLE_IllegalArg',
+    6: 'CPLE_NotSupported',
+    7: 'CPLE_AssertionFailed',
+    8: 'CPLE_NoWriteAccess',
+    9: 'CPLE_UserInterrupt',
+    10: 'CPLE_ObjectNull'
+}
+
 cdef void * errorHandler(int eErrClass, int err_no, char *msg):
-    log.log(code_map[eErrClass], "OGR Error %s: %s", err_no, msg)
+    log.log(level_map[eErrClass], "%s in %s", code_map[err_no], msg)
 
 
 def driver_count():
-    return GDALGetDriverCount() + OGRGetDriverCount()
+    return OGRGetDriverCount()
 
 
 cdef class GDALEnv(object):
-    
-    cdef object is_chef
-    cdef object options
 
-    def __init__(self, is_chef=True, **options):
-        self.is_chef = is_chef
+    cdef public object options
+
+    def __init__(self, **options):
         self.options = options.copy()
 
     def __enter__(self):
-        cdef const char *key_c
-        cdef const char *val_c
+        self.start()
+        return self
+
+    def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
+        self.stop()
+
+    def start(self):
+        cdef const char *key_c = NULL
+        cdef const char *val_c = NULL
+
+        if GDALGetDriverCount() == 0:
+            GDALAllRegister()
+        if OGRGetDriverCount() == 0:
+            OGRRegisterAll()
         CPLSetErrorHandler(<void *>errorHandler)
-        GDALAllRegister()
-        OGRRegisterAll()
-        if driver_count() == 0:
+        if OGRGetDriverCount() == 0:
             raise ValueError("Drivers not registered")
+
+        if 'GDAL_DATA' not in os.environ:
+            whl_datadir = os.path.abspath(
+                os.path.join(os.path.dirname(__file__), "gdal_data"))
+            share_datadir = os.path.join(sys.prefix, 'share/gdal')
+            if os.path.exists(os.path.join(whl_datadir, 'pcs.csv')):
+                os.environ['GDAL_DATA'] = whl_datadir
+            elif os.path.exists(os.path.join(share_datadir, 'pcs.csv')):
+                os.environ['GDAL_DATA'] = share_datadir
+        if 'PROJ_LIB' not in os.environ:
+            whl_datadir = os.path.abspath(
+                os.path.join(os.path.dirname(__file__), "proj_data"))
+            os.environ['PROJ_LIB'] = whl_datadir
+
         for key, val in self.options.items():
             key_b = key.upper().encode('utf-8')
             key_c = key_b
@@ -76,10 +126,154 @@ cdef class GDALEnv(object):
             log.debug("Option %s=%s", key, CPLGetConfigOption(key_c, NULL))
         return self
 
-    def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
-        cdef const char *key_c
+    def stop(self):
+        cdef const char *key_c = NULL
         for key in self.options:
             key_b = key.upper().encode('utf-8')
             key_c = key_b
             CPLSetThreadLocalConfigOption(key_c, NULL)
         CPLSetErrorHandler(NULL)
+
+    def drivers(self):
+        cdef void *drv = NULL
+        cdef char *key = NULL
+        cdef char *val = NULL
+        cdef int i
+        result = {}
+        for i in range(OGRGetDriverCount()):
+            drv = OGRGetDriver(i)
+            key = OGR_Dr_GetName(drv)
+            key_b = key
+            val = OGR_Dr_GetName(drv)
+            val_b = val
+            result[key_b.decode('utf-8')] = val_b.decode('utf-8')
+        return result
+
+
+# Here is the list of available drivers as (name, modes) tuples. Currently,
+# we only expose the defaults (excepting FileGDB). We also don't expose
+# the CSV or GeoJSON drivers. Use Python's csv and json modules instead.
+# Might still exclude a few more of these after making a pass through the
+# entries for each at http://www.gdal.org/ogr/ogr_formats.html to screen
+# out the multi-layer formats.
+
+supported_drivers = dict([
+#OGR Vector Formats
+#Format Name 	Code 	Creation 	Georeferencing 	Compiled by default
+#Aeronav FAA files 	AeronavFAA 	No 	Yes 	Yes
+    ("AeronavFAA", "r"),
+#ESRI ArcObjects 	ArcObjects 	No 	Yes 	No, needs ESRI ArcObjects
+#Arc/Info Binary Coverage 	AVCBin 	No 	Yes 	Yes
+# multi-layer
+#   ("AVCBin", "r"),
+#Arc/Info .E00 (ASCII) Coverage 	AVCE00 	No 	Yes 	Yes
+# multi-layer
+#    ("AVCE00", "r"),
+#Arc/Info Generate 	ARCGEN 	No 	No 	Yes
+    ("ARCGEN", "r"),
+#Atlas BNA 	BNA 	Yes 	No 	Yes
+    ("BNA", "raw"),
+#AutoCAD DWG 	DWG 	No 	No 	No
+#AutoCAD DXF 	DXF 	Yes 	No 	Yes
+    ("DXF", "raw"),
+#Comma Separated Value (.csv) 	CSV 	Yes 	No 	Yes
+#CouchDB / GeoCouch 	CouchDB 	Yes 	Yes 	No, needs libcurl
+#DODS/OPeNDAP 	DODS 	No 	Yes 	No, needs libdap
+#EDIGEO 	EDIGEO 	No 	Yes 	Yes
+# multi-layer? Hard to tell from the OGR docs
+#   ("EDIGEO", "r"),
+#ElasticSearch 	ElasticSearch 	Yes (write-only) 	- 	No, needs libcurl
+#ESRI FileGDB 	FileGDB 	Yes 	Yes 	No, needs FileGDB API library
+# multi-layer
+    ("FileGDB", "raw"),
+#ESRI Personal GeoDatabase 	PGeo 	No 	Yes 	No, needs ODBC library
+#ESRI ArcSDE 	SDE 	No 	Yes 	No, needs ESRI SDE
+#ESRI Shapefile 	ESRI Shapefile 	Yes 	Yes 	Yes
+    ("ESRI Shapefile", "raw"),
+#FMEObjects Gateway 	FMEObjects Gateway 	No 	Yes 	No, needs FME
+#GeoJSON 	GeoJSON 	Yes 	Yes 	Yes
+    ("GeoJSON", "rw"),
+#Géoconcept Export 	Geoconcept 	Yes 	Yes 	Yes
+# multi-layers
+#   ("Geoconcept", "raw"),
+#Geomedia .mdb 	Geomedia 	No 	No 	No, needs ODBC library
+#GeoPackage	GPKG	Yes	Yes	No, needs libsqlite3
+    ("GPKG", "rw"),
+#GeoRSS 	GeoRSS 	Yes 	Yes 	Yes (read support needs libexpat)
+#Google Fusion Tables 	GFT 	Yes 	Yes 	No, needs libcurl
+#GML 	GML 	Yes 	Yes 	Yes (read support needs Xerces or libexpat)
+#GMT 	GMT 	Yes 	Yes 	Yes
+    ("GMT", "raw"),
+#GPSBabel 	GPSBabel 	Yes 	Yes 	Yes (needs GPSBabel and GPX driver)
+#GPX 	GPX 	Yes 	Yes 	Yes (read support needs libexpat)
+    ("GPX", "raw"),
+#GRASS 	GRASS 	No 	Yes 	No, needs libgrass
+#GPSTrackMaker (.gtm, .gtz) 	GPSTrackMaker 	Yes 	Yes 	Yes
+    ("GPSTrackMaker", "raw"),
+#Hydrographic Transfer Format 	HTF 	No 	Yes 	Yes
+# TODO: Fiona is not ready for multi-layer formats: ("HTF", "r"),
+#Idrisi Vector (.VCT) 	Idrisi 	No 	Yes 	Yes
+    ("Idrisi", "r"),
+#Informix DataBlade 	IDB 	Yes 	Yes 	No, needs Informix DataBlade
+#INTERLIS 	"Interlis 1" and "Interlis 2" 	Yes 	Yes 	No, needs Xerces (INTERLIS model reading needs ili2c.jar)
+#INGRES 	INGRES 	Yes 	No 	No, needs INGRESS
+#KML 	KML 	Yes 	Yes 	Yes (read support needs libexpat)
+#LIBKML 	LIBKML 	Yes 	Yes 	No, needs libkml
+#Mapinfo File 	MapInfo File 	Yes 	Yes 	Yes
+    ("MapInfo File", "raw"),
+#Microstation DGN 	DGN 	Yes 	No 	Yes
+    ("DGN", "raw"),
+#Access MDB (PGeo and Geomedia capable) 	MDB 	No 	Yes 	No, needs JDK/JRE
+#Memory 	Memory 	Yes 	Yes 	Yes
+#MySQL 	MySQL 	No 	Yes 	No, needs MySQL library
+#NAS - ALKIS 	NAS 	No 	Yes 	No, needs Xerces
+#Oracle Spatial 	OCI 	Yes 	Yes 	No, needs OCI library
+#ODBC 	ODBC 	No 	Yes 	No, needs ODBC library
+#MS SQL Spatial 	MSSQLSpatial 	Yes 	Yes 	No, needs ODBC library
+#Open Document Spreadsheet 	ODS 	Yes 	No 	No, needs libexpat
+#OGDI Vectors (VPF, VMAP, DCW) 	OGDI 	No 	Yes 	No, needs OGDI library
+#OpenAir 	OpenAir 	No 	Yes 	Yes
+# multi-layer
+#   ("OpenAir", "r"),
+#PCI Geomatics Database File 	PCIDSK 	No 	No 	Yes, using internal PCIDSK SDK (from GDAL 1.7.0)
+    ("PCIDSK", "r"),
+#PDS 	PDS 	No 	Yes 	Yes
+    ("PDS", "r"),
+#PGDump 	PostgreSQL SQL dump 	Yes 	Yes 	Yes
+#PostgreSQL/PostGIS 	PostgreSQL/PostGIS 	Yes 	Yes 	No, needs PostgreSQL client library (libpq)
+#EPIInfo .REC 	REC 	No 	No 	Yes
+#S-57 (ENC) 	S57 	No 	Yes 	Yes
+# multi-layer
+#   ("S57", "r"),
+#SDTS 	SDTS 	No 	Yes 	Yes
+# multi-layer
+#   ("SDTS", "r"),
+#SEG-P1 / UKOOA P1/90 	SEGUKOOA 	No 	Yes 	Yes
+# multi-layers
+#   ("SEGUKOOA", "r"),
+#SEG-Y 	SEGY 	No 	No 	Yes
+    ("SEGY", "r"),
+#Norwegian SOSI Standard 	SOSI 	No 	Yes 	No, needs FYBA library
+#SQLite/SpatiaLite 	SQLite 	Yes 	Yes 	No, needs libsqlite3 or libspatialite
+#SUA 	SUA 	No 	Yes 	Yes
+    ("SUA", "r"),
+#SVG 	SVG 	No 	Yes 	No, needs libexpat
+#UK .NTF 	UK. NTF 	No 	Yes 	Yes
+# multi-layer
+#   ("UK. NTF", "r"),
+#U.S. Census TIGER/Line 	TIGER 	No 	Yes 	Yes
+# multi-layer
+#   ("TIGER", "r"),
+#VFK data 	VFK 	No 	Yes 	Yes
+# multi-layer
+#   ("VFK", "r"),
+#VRT - Virtual Datasource 	VRT 	No 	Yes 	Yes
+# multi-layer
+#   ("VRT", "r"),
+#OGC WFS (Web Feature Service) 	WFS 	Yes 	Yes 	No, needs libcurl
+#MS Excel format 	XLS 	No 	No 	No, needs libfreexl
+#Office Open XML spreadsheet 	XLSX 	Yes 	No 	No, needs libexpat
+#X-Plane/Flighgear aeronautical data 	XPLANE 	No 	Yes 	Yes
+# multi-layer
+#   ("XPLANE", "r") 
+])
diff --git a/fiona/collection.py b/fiona/collection.py
index 02a0e61..3478b7b 100644
--- a/fiona/collection.py
+++ b/fiona/collection.py
@@ -6,9 +6,10 @@ import sys
 
 from fiona.ogrext import Iterator, ItemsIterator, KeysIterator
 from fiona.ogrext import Session, WritingSession
-from fiona.ogrext import calc_gdal_version_num, get_gdal_version_num, get_gdal_release_name
+from fiona.ogrext import (
+    calc_gdal_version_num, get_gdal_version_num, get_gdal_release_name)
 from fiona.errors import DriverError, SchemaError, CRSError
-from fiona._drivers import driver_count, GDALEnv
+from fiona._drivers import driver_count, GDALEnv, supported_drivers
 from six import string_types
 
 class Collection(object):
@@ -23,6 +24,7 @@ class Collection(object):
             layer=None,
             vsi=None,
             archive=None,
+            enabled_drivers=None,
             **kwargs):
         
         """The required ``path`` is the absolute or relative path to
@@ -74,6 +76,7 @@ class Collection(object):
         self._crs = None
         self._crs_wkt = None
         self.env = None
+        self.enabled_drivers = enabled_drivers
         
         self.path = vsi_path(path, vsi, archive)
         
@@ -124,12 +127,13 @@ class Collection(object):
         
         if driver_count == 0:
             # create a local manager and enter
-            self.env = GDALEnv(True)
+            self.env = GDALEnv()
         else:
-            self.env = GDALEnv(False)
+            self.env = GDALEnv()
         self.env.__enter__()
 
         if self.mode == "r":
+            self._driver = driver
             self.encoding = encoding
             self.session = Session()
             self.session.start(self)
@@ -139,6 +143,7 @@ class Collection(object):
             self.encoding = encoding or self.session.get_fileencoding().lower()
 
         elif self.mode in ("a", "w"):
+            self._driver = driver
             self.encoding = encoding
             self.session = WritingSession()
             self.session.start(self, **kwargs)
@@ -351,6 +356,10 @@ class Collection(object):
     def __len__(self):
         if self._len <= 0 and self.session is not None:
             self._len = self.session.get_length()
+        if self._len < 0:
+            # Raise TypeError when we don't know the length so that Python
+            # will treat Collection as a generator
+            raise TypeError("Layer does not support counting")
         return self._len
 
     @property
@@ -408,133 +417,3 @@ def vsi_path(path, vsi=None, archive=None):
     else:
         result = path
     return result
-
-
-# Here is the list of available drivers as (name, modes) tuples. Currently,
-# we only expose the defaults (excepting FileGDB). We also don't expose
-# the CSV or GeoJSON drivers. Use Python's csv and json modules instead.
-# Might still exclude a few more of these after making a pass through the
-# entries for each at http://www.gdal.org/ogr/ogr_formats.html to screen
-# out the multi-layer formats.
-
-supported_drivers = dict([
-#OGR Vector Formats
-#Format Name 	Code 	Creation 	Georeferencing 	Compiled by default
-#Aeronav FAA files 	AeronavFAA 	No 	Yes 	Yes
-    ("AeronavFAA", "r"),
-#ESRI ArcObjects 	ArcObjects 	No 	Yes 	No, needs ESRI ArcObjects
-#Arc/Info Binary Coverage 	AVCBin 	No 	Yes 	Yes
-# multi-layer
-#   ("AVCBin", "r"),
-#Arc/Info .E00 (ASCII) Coverage 	AVCE00 	No 	Yes 	Yes
-# multi-layer
-#    ("AVCE00", "r"),
-#Arc/Info Generate 	ARCGEN 	No 	No 	Yes
-    ("ARCGEN", "r"),
-#Atlas BNA 	BNA 	Yes 	No 	Yes
-    ("BNA", "raw"),
-#AutoCAD DWG 	DWG 	No 	No 	No
-#AutoCAD DXF 	DXF 	Yes 	No 	Yes
-    ("DXF", "raw"),
-#Comma Separated Value (.csv) 	CSV 	Yes 	No 	Yes
-#CouchDB / GeoCouch 	CouchDB 	Yes 	Yes 	No, needs libcurl
-#DODS/OPeNDAP 	DODS 	No 	Yes 	No, needs libdap
-#EDIGEO 	EDIGEO 	No 	Yes 	Yes
-# multi-layer? Hard to tell from the OGR docs
-#   ("EDIGEO", "r"),
-#ElasticSearch 	ElasticSearch 	Yes (write-only) 	- 	No, needs libcurl
-#ESRI FileGDB 	FileGDB 	Yes 	Yes 	No, needs FileGDB API library
-# multi-layer
-    ("FileGDB", "raw"),
-#ESRI Personal GeoDatabase 	PGeo 	No 	Yes 	No, needs ODBC library
-#ESRI ArcSDE 	SDE 	No 	Yes 	No, needs ESRI SDE
-#ESRI Shapefile 	ESRI Shapefile 	Yes 	Yes 	Yes
-    ("ESRI Shapefile", "raw"),
-#FMEObjects Gateway 	FMEObjects Gateway 	No 	Yes 	No, needs FME
-#GeoJSON 	GeoJSON 	Yes 	Yes 	Yes
-    ("GeoJSON", "rw"),
-#Géoconcept Export 	Geoconcept 	Yes 	Yes 	Yes
-# multi-layers
-#   ("Geoconcept", "raw"),
-#Geomedia .mdb 	Geomedia 	No 	No 	No, needs ODBC library
-#GeoPackage	GPKG	Yes	Yes	No, needs libsqlite3
-    ("GPKG", "rw"),
-#GeoRSS 	GeoRSS 	Yes 	Yes 	Yes (read support needs libexpat)
-#Google Fusion Tables 	GFT 	Yes 	Yes 	No, needs libcurl
-#GML 	GML 	Yes 	Yes 	Yes (read support needs Xerces or libexpat)
-#GMT 	GMT 	Yes 	Yes 	Yes
-    ("GMT", "raw"),
-#GPSBabel 	GPSBabel 	Yes 	Yes 	Yes (needs GPSBabel and GPX driver)
-#GPX 	GPX 	Yes 	Yes 	Yes (read support needs libexpat)
-    ("GPX", "raw"),
-#GRASS 	GRASS 	No 	Yes 	No, needs libgrass
-#GPSTrackMaker (.gtm, .gtz) 	GPSTrackMaker 	Yes 	Yes 	Yes
-    ("GPSTrackMaker", "raw"),
-#Hydrographic Transfer Format 	HTF 	No 	Yes 	Yes
-# TODO: Fiona is not ready for multi-layer formats: ("HTF", "r"),
-#Idrisi Vector (.VCT) 	Idrisi 	No 	Yes 	Yes
-    ("Idrisi", "r"),
-#Informix DataBlade 	IDB 	Yes 	Yes 	No, needs Informix DataBlade
-#INTERLIS 	"Interlis 1" and "Interlis 2" 	Yes 	Yes 	No, needs Xerces (INTERLIS model reading needs ili2c.jar)
-#INGRES 	INGRES 	Yes 	No 	No, needs INGRESS
-#KML 	KML 	Yes 	Yes 	Yes (read support needs libexpat)
-#LIBKML 	LIBKML 	Yes 	Yes 	No, needs libkml
-#Mapinfo File 	MapInfo File 	Yes 	Yes 	Yes
-    ("MapInfo File", "raw"),
-#Microstation DGN 	DGN 	Yes 	No 	Yes
-    ("DGN", "raw"),
-#Access MDB (PGeo and Geomedia capable) 	MDB 	No 	Yes 	No, needs JDK/JRE
-#Memory 	Memory 	Yes 	Yes 	Yes
-#MySQL 	MySQL 	No 	Yes 	No, needs MySQL library
-#NAS - ALKIS 	NAS 	No 	Yes 	No, needs Xerces
-#Oracle Spatial 	OCI 	Yes 	Yes 	No, needs OCI library
-#ODBC 	ODBC 	No 	Yes 	No, needs ODBC library
-#MS SQL Spatial 	MSSQLSpatial 	Yes 	Yes 	No, needs ODBC library
-#Open Document Spreadsheet 	ODS 	Yes 	No 	No, needs libexpat
-#OGDI Vectors (VPF, VMAP, DCW) 	OGDI 	No 	Yes 	No, needs OGDI library
-#OpenAir 	OpenAir 	No 	Yes 	Yes
-# multi-layer
-#   ("OpenAir", "r"),
-#PCI Geomatics Database File 	PCIDSK 	No 	No 	Yes, using internal PCIDSK SDK (from GDAL 1.7.0)
-    ("PCIDSK", "r"),
-#PDS 	PDS 	No 	Yes 	Yes
-    ("PDS", "r"),
-#PGDump 	PostgreSQL SQL dump 	Yes 	Yes 	Yes
-#PostgreSQL/PostGIS 	PostgreSQL/PostGIS 	Yes 	Yes 	No, needs PostgreSQL client library (libpq)
-#EPIInfo .REC 	REC 	No 	No 	Yes
-#S-57 (ENC) 	S57 	No 	Yes 	Yes
-# multi-layer
-#   ("S57", "r"),
-#SDTS 	SDTS 	No 	Yes 	Yes
-# multi-layer
-#   ("SDTS", "r"),
-#SEG-P1 / UKOOA P1/90 	SEGUKOOA 	No 	Yes 	Yes
-# multi-layers
-#   ("SEGUKOOA", "r"),
-#SEG-Y 	SEGY 	No 	No 	Yes
-    ("SEGY", "r"),
-#Norwegian SOSI Standard 	SOSI 	No 	Yes 	No, needs FYBA library
-#SQLite/SpatiaLite 	SQLite 	Yes 	Yes 	No, needs libsqlite3 or libspatialite
-#SUA 	SUA 	No 	Yes 	Yes
-    ("SUA", "r"),
-#SVG 	SVG 	No 	Yes 	No, needs libexpat
-#UK .NTF 	UK. NTF 	No 	Yes 	Yes
-# multi-layer
-#   ("UK. NTF", "r"),
-#U.S. Census TIGER/Line 	TIGER 	No 	Yes 	Yes
-# multi-layer
-#   ("TIGER", "r"),
-#VFK data 	VFK 	No 	Yes 	Yes
-# multi-layer
-#   ("VFK", "r"),
-#VRT - Virtual Datasource 	VRT 	No 	Yes 	Yes
-# multi-layer
-#   ("VRT", "r"),
-#OGC WFS (Web Feature Service) 	WFS 	Yes 	Yes 	No, needs libcurl
-#MS Excel format 	XLS 	No 	No 	No, needs libfreexl
-#Office Open XML spreadsheet 	XLSX 	Yes 	No 	No, needs libexpat
-#X-Plane/Flighgear aeronautical data 	XPLANE 	No 	Yes 	Yes
-# multi-layer
-#   ("XPLANE", "r") 
-])
-
diff --git a/fiona/errors.py b/fiona/errors.py
index d00af0c..ac48847 100644
--- a/fiona/errors.py
+++ b/fiona/errors.py
@@ -9,3 +9,6 @@ class SchemaError(FionaValueError):
 
 class CRSError(FionaValueError):
     """When a crs mapping has neither init or proj items."""
+
+class DataIOError(IOError):
+    """IO errors involving driver registration or availability"""
diff --git a/fiona/fio/bounds.py b/fiona/fio/bounds.py
index cf30132..f35398f 100644
--- a/fiona/fio/bounds.py
+++ b/fiona/fio/bounds.py
@@ -3,6 +3,7 @@ import logging
 import sys
 
 import click
+from cligj import precision_opt, use_rs_opt
 
 import fiona
 from fiona.fio.cli import cli, obj_gen
@@ -10,8 +11,7 @@ from fiona.fio.cli import cli, obj_gen
 
 # Bounds command
 @cli.command(short_help="Print the extent of GeoJSON objects")
- at click.option('--precision', type=int, default=-1, metavar="N",
-              help="Decimal precision of coordinates.")
+ at precision_opt
 @click.option('--explode/--no-explode', default=False,
               help="Explode collections into features (default: no).")
 @click.option('--with-id/--without-id', default=False,
@@ -20,11 +20,9 @@ from fiona.fio.cli import cli, obj_gen
 @click.option('--with-obj/--without-obj', default=False,
               help="Print GeoJSON objects and bounding boxes together "
                    "(default: without).")
- at click.option('--x-json-seq-rs/--x-json-seq-no-rs', default=False,
-              help="Use RS as text separator instead of LF. "
-                   "Experimental (default: no).")
+ at use_rs_opt
 @click.pass_context
-def bounds(ctx, precision, explode, with_id, with_obj, x_json_seq_rs):
+def bounds(ctx, precision, explode, with_id, with_obj, use_rs):
     """Print the bounding boxes of GeoJSON objects read from stdin.
     
     Optionally explode collections and print the bounds of their
@@ -62,8 +60,9 @@ def bounds(ctx, precision, explode, with_id, with_obj, x_json_seq_rs):
                         rec = feat
                     else:
                         rec = (w, s, e, n)
-                    stdout.write(json.dumps(rec))
-                    stdout.write('\n')
+                    if use_rs:
+                        click.echo(u'\u001e', nl=False)
+                    click.echo(json.dumps(rec))
                 else:
                     xs.extend([w, e])
                     ys.extend([s, n])
@@ -76,8 +75,9 @@ def bounds(ctx, precision, explode, with_id, with_obj, x_json_seq_rs):
                     rec = obj
                 else:
                     rec = (w, s, e, n)
-                stdout.write(json.dumps(rec))
-                stdout.write('\n')
+                if use_rs:
+                    click.echo(u'\u001e', nl=False)
+                click.echo(json.dumps(rec))
 
         sys.exit(0)
     except Exception:
diff --git a/fiona/fio/cat.py b/fiona/fio/cat.py
index e650cbd..b97d1ba 100644
--- a/fiona/fio/cat.py
+++ b/fiona/fio/cat.py
@@ -4,6 +4,8 @@ import logging
 import sys
 
 import click
+from cligj import files_in_arg
+from cligj import precision_opt, indent_opt, compact_opt, use_rs_opt
 
 import fiona
 from fiona.transform import transform_geom
@@ -61,34 +63,24 @@ def id_record(rec):
 
 # Cat command
 @cli.command(short_help="Concatenate and print the features of datasets")
-# One or more files.
- at click.argument('input', nargs=-1, type=click.Path(exists=True))
-# Coordinate precision option.
- at click.option('--precision', type=int, default=-1, metavar="N",
-              help="Decimal precision of coordinates.")
- at click.option('--indent', default=None, type=int, metavar="N",
-              help="Indentation level for pretty printed output.")
- at click.option('--compact/--no-compact', default=False,
-              help="Use compact separators (',', ':').")
+ at files_in_arg
+ at precision_opt
+ at indent_opt
+ at compact_opt
 @click.option('--ignore-errors/--no-ignore-errors', default=False,
               help="log errors but do not stop serialization.")
 @click.option('--dst_crs', default=None, metavar="EPSG:NNNN",
               help="Destination CRS.")
-# Use ASCII RS control code to signal a sequence item (False is default).
-# See http://tools.ietf.org/html/draft-ietf-json-text-sequence-05.
-# Experimental.
- at click.option('--x-json-seq-rs/--x-json-seq-no-rs', default=True,
-        help="Use RS as text separator instead of LF. Experimental.")
+ at use_rs_opt
 @click.option('--bbox', default=None, metavar="w,s,e,n",
               help="filter for features intersecting a bounding box")
 @click.pass_context
-def cat(ctx, input, precision, indent, compact, ignore_errors, dst_crs,
-        x_json_seq_rs, bbox):
+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."""
     verbosity = (ctx.obj and ctx.obj['verbosity']) or 2
     logger = logging.getLogger('fio')
-    sink = click.get_text_stream('stdout')
 
     dump_kwds = {'sort_keys': True}
     if indent:
@@ -99,10 +91,13 @@ def cat(ctx, input, precision, indent, compact, ignore_errors, dst_crs,
 
     try:
         with fiona.drivers(CPL_DEBUG=verbosity>2):
-            for path in input:
+            for path in files:
                 with fiona.open(path) as src:
                     if bbox:
-                        bbox = tuple(map(float, bbox.split(',')))
+                        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(
@@ -111,10 +106,9 @@ def cat(ctx, input, precision, indent, compact, ignore_errors, dst_crs,
                                     precision=precision)
                             feat['geometry'] = g
                             feat['bbox'] = fiona.bounds(g)
-                        if x_json_seq_rs:
-                            sink.write(u'\u001e')
-                        json.dump(feat, sink, **dump_kwds)
-                        sink.write("\n")
+                        if use_rs:
+                            click.echo(u'\u001e', nl=False)
+                        click.echo(json.dumps(feat, **dump_kwds))
         sys.exit(0)
     except Exception:
         logger.exception("Failed. Exception caught")
@@ -123,13 +117,9 @@ def cat(ctx, input, precision, indent, compact, ignore_errors, dst_crs,
 
 # Collect command
 @cli.command(short_help="Collect a sequence of features.")
-# Coordinate precision option.
- at click.option('--precision', type=int, default=-1, metavar="N",
-              help="Decimal precision of coordinates.")
- at click.option('--indent', default=None, type=int, metavar="N",
-              help="Indentation level for pretty printed output.")
- at click.option('--compact/--no-compact', default=False,
-              help="Use compact separators (',', ':').")
+ at precision_opt
+ at indent_opt
+ at compact_opt
 @click.option('--record-buffered/--no-record-buffered', default=False,
               help="Economical buffering of writes at record, not collection "
               "(default), level.")
@@ -303,17 +293,14 @@ def collect(ctx, precision, indent, compact, record_buffered, ignore_errors,
 
 # Distribute command
 @cli.command(short_help="Distribute features from a collection")
- at click.option('--x-json-seq-rs/--x-json-seq-no-rs', default=False,
-              help="Use RS as text separator instead of LF. "
-                   "Experimental (default: no).")
+ at use_rs_opt
 @click.pass_context
-def distrib(ctx, x_json_seq_rs):
+def distrib(ctx, use_rs):
     """Print the features of GeoJSON objects read from stdin.
     """
     verbosity = (ctx.obj and ctx.obj['verbosity']) or 2
     logger = logging.getLogger('fio')
     stdin = click.get_text_stream('stdin')
-    stdout = click.get_text_stream('stdout')
     try:
         source = obj_gen(stdin)
         for i, obj in enumerate(source):
@@ -324,25 +311,21 @@ def distrib(ctx, x_json_seq_rs):
                     feat['parent'] = obj_id
                 feat_id = feat.get('id', 'feature:' + str(i))
                 feat['id'] = feat_id
-                stdout.write(json.dumps(feat))
-                stdout.write('\n')
+                if use_rs:
+                    click.echo(u'\u001e', nl=False)
+                click.echo(json.dumps(feat))
         sys.exit(0)
     except Exception:
-        logger.exception("Failed. Exception caught")
-        sys.exit(1)
+        raise
 
 
 # Dump command
 @cli.command(short_help="Dump a dataset to GeoJSON.")
 @click.argument('input', type=click.Path(), required=True)
 @click.option('--encoding', help="Specify encoding of the input file.")
-# Coordinate precision option.
- at click.option('--precision', type=int, default=-1,
-              help="Decimal precision of coordinates.")
- at click.option('--indent', default=None, type=int,
-              help="Indentation level for pretty printed output.")
- at click.option('--compact/--no-compact', default=False,
-              help="Use compact separators (',', ':').")
+ at precision_opt
+ at indent_opt
+ at compact_opt
 @click.option('--record-buffered/--no-record-buffered', default=False,
     help="Economical buffering of writes at record, not collection "
          "(default), level.")
@@ -353,18 +336,9 @@ def distrib(ctx, x_json_seq_rs):
 
 @click.option('--add-ld-context-item', multiple=True,
         help="map a term to a URI and add it to the output's JSON LD context.")
- at click.option('--x-json-seq/--x-json-obj', default=False,
-    help="Write a LF-delimited JSON sequence (default is object). "
-         "Experimental.")
-# Use ASCII RS control code to signal a sequence item (False is default).
-# See http://tools.ietf.org/html/draft-ietf-json-text-sequence-05.
-# Experimental.
- at click.option('--x-json-seq-rs/--x-json-seq-no-rs', default=True,
-        help="Use RS as text separator. Experimental.")
 @click.pass_context
 def dump(ctx, input, encoding, precision, indent, compact, record_buffered,
-         ignore_errors, with_ld_context, add_ld_context_item,
-         x_json_seq, x_json_seq_rs):
+         ignore_errors, with_ld_context, add_ld_context_item):
     """Dump a dataset either as a GeoJSON feature collection (the default)
     or a sequence of GeoJSON features."""
     verbosity = (ctx.obj and ctx.obj['verbosity']) or 2
@@ -394,15 +368,7 @@ def dump(ctx, input, encoding, precision, indent, compact, record_buffered,
                 meta = source.meta
                 meta['fields'] = dict(source.schema['properties'].items())
 
-                if x_json_seq:
-                    for feat in source:
-                        feat = transformer(source.crs, feat)
-                        if x_json_seq_rs:
-                            sink.write(u'\u001e')
-                        json.dump(feat, sink, **dump_kwds)
-                        sink.write("\n")
-
-                elif record_buffered:
+                if record_buffered:
                     # Buffer GeoJSON data at the feature level for smaller
                     # memory footprint.
                     indented = bool(indent)
diff --git a/fiona/fio/cli.py b/fiona/fio/cli.py
index 9ad6bd8..bb120e8 100644
--- a/fiona/fio/cli.py
+++ b/fiona/fio/cli.py
@@ -4,6 +4,7 @@ import sys
 import warnings
 
 import click
+from cligj import verbose_opt, quiet_opt
 
 from fiona import __version__ as fio_version
 
@@ -24,8 +25,8 @@ def print_version(ctx, param, value):
 
 # The CLI command group.
 @click.group(help="Fiona command line interface.")
- at click.option('--verbose', '-v', count=True, help="Increase verbosity.")
- at click.option('--quiet', '-q', count=True, help="Decrease verbosity.")
+ at verbose_opt
+ at quiet_opt
 @click.option('--version', is_flag=True, callback=print_version,
               expose_value=False, is_eager=True,
               help="Print Fiona version.")
diff --git a/fiona/fio/fio.py b/fiona/fio/fio.py
index 925eebe..989c16a 100644
--- a/fiona/fio/fio.py
+++ b/fiona/fio/fio.py
@@ -4,6 +4,7 @@
 
 import code
 from functools import partial
+import itertools
 import json
 import logging
 import pprint
@@ -11,6 +12,7 @@ import sys
 import warnings
 
 import click
+from cligj import indent_opt, sequence_opt
 import six.moves
 
 import fiona
@@ -50,8 +52,7 @@ def env(ctx, key):
 @cli.command(short_help="Print information about a dataset.")
 # One or more files.
 @click.argument('input', type=click.Path(exists=True))
- at click.option('--indent', default=None, type=int, 
-              help="Indentation level for pretty printed output.")
+ at indent_opt
 # Options to pick out a single metadata item and print it as
 # a string.
 @click.option('--count', 'meta_member', flag_value='count',
@@ -61,13 +62,12 @@ def env(ctx, key):
 @click.option('--crs', 'meta_member', flag_value='crs',
               help="Print the CRS as a PROJ.4 string.")
 @click.option('--bounds', 'meta_member', flag_value='bounds',
-              help="Print the nodata value.")
+              help="Print the boundary coordinates "
+                   "(left, bottom, right, top).")
 @click.pass_context
 def info(ctx, input, indent, meta_member):
-    verbosity = ctx.obj['verbosity']
+    verbosity = (ctx.obj and ctx.obj['verbosity']) or 2
     logger = logging.getLogger('rio')
-
-    stdout = click.get_text_stream('stdout')
     try:
         with fiona.drivers(CPL_DEBUG=verbosity>2):
             with fiona.open(input) as src:
@@ -79,12 +79,11 @@ def info(ctx, input, indent, meta_member):
                 info['crs'] = proj4
                 if meta_member:
                     if isinstance(info[meta_member], (list, tuple)):
-                        print(" ".join(map(str, info[meta_member])))
+                        click.echo(" ".join(map(str, info[meta_member])))
                     else:
-                        print(info[meta_member])
+                        click.echo(info[meta_member])
                 else:
-                    stdout.write(json.dumps(info, indent=indent))
-                    stdout.write("\n")
+                    click.echo(json.dumps(info, indent=indent))
         sys.exit(0)
     except Exception:
         logger.exception("Failed. Exception caught")
@@ -95,7 +94,7 @@ def info(ctx, input, indent, meta_member):
 @click.argument('src_path', type=click.Path(exists=True))
 @click.pass_context
 def insp(ctx, src_path):
-    verbosity = ctx.obj['verbosity']
+    verbosity = (ctx.obj and ctx.obj['verbosity']) or 2
     logger = logging.getLogger('fio')
     try:
         with fiona.drivers(CPL_DEBUG=verbosity>2):
@@ -120,16 +119,15 @@ def insp(ctx, src_path):
               help="Output format driver name.")
 @click.option('--src_crs', default=None, help="Source CRS.")
 @click.option('--dst_crs', default=None, help="Destination CRS.")
- at click.option('--x-json-seq/--x-json-obj', default=False,
-              help="Read a LF-delimited JSON sequence (default is object). Experimental.")
+ at sequence_opt
 @click.pass_context
 
-def load(ctx, output, driver, src_crs, dst_crs, x_json_seq):
+def load(ctx, output, driver, src_crs, dst_crs, sequence):
     """Load features from JSON to a file in another format.
 
     The input is a GeoJSON feature collection or optionally a sequence of
     GeoJSON feature objects."""
-    verbosity = ctx.obj['verbosity']
+    verbosity = (ctx.obj and ctx.obj['verbosity']) or 2
     logger = logging.getLogger('fio')
     stdin = click.get_text_stream('stdin')
 
@@ -158,7 +156,7 @@ def load(ctx, output, driver, src_crs, dst_crs, x_json_seq):
                 feat = json.loads(buffer)
                 feat['geometry'] = transformer(feat['geometry'])
                 yield feat
-    elif x_json_seq:
+    elif sequence:
         def feature_gen():
             yield json.loads(first_line)
             for line in stdin:
@@ -167,7 +165,8 @@ def load(ctx, output, driver, src_crs, dst_crs, x_json_seq):
                 yield feat
     else:
         def feature_gen():
-            for feat in json.load(input)['features']:
+            text = "".join(itertools.chain([first_line], stdin))
+            for feat in json.loads(text)['features']:
                 feat['geometry'] = transformer(feat['geometry'])
                 yield feat
 
@@ -179,7 +178,7 @@ def load(ctx, output, driver, src_crs, dst_crs, x_json_seq):
         first = next(source)
         schema = {'geometry': first['geometry']['type']}
         schema['properties'] = dict([
-            (k, FIELD_TYPES_MAP_REV[type(v)])
+            (k, FIELD_TYPES_MAP_REV.get(type(v)) or 'str')
             for k, v in first['properties'].items()])
 
         with fiona.drivers(CPL_DEBUG=verbosity>2):
diff --git a/fiona/ograpi.pxd b/fiona/ograpi.pxd
index 7945c55..de1abfe 100644
--- a/fiona/ograpi.pxd
+++ b/fiona/ograpi.pxd
@@ -49,8 +49,9 @@ cdef extern from "ogr_srs_api.h":
 
 cdef extern from "ogr_api.h":
     char *  OGR_Dr_GetName (void *driver)
-    void *  OGR_Dr_CreateDataSource (void *driver, char *path, char **options)
+    void *  OGR_Dr_CreateDataSource (void *driver, const char *path, char **options)
     int     OGR_Dr_DeleteDataSource (void *driver, char *)
+    void *  OGR_Dr_Open (void *driver, const char *path, int bupdate)
     int     OGR_DS_DeleteLayer (void *datasource, int n)
     void *  OGR_DS_CreateLayer (void *datasource, char *name, void *crs, int geomType, char **options)
     void *  OGR_DS_ExecuteSQL (void *datasource, char *name, void *filter, char *dialext)
diff --git a/fiona/ogrext.pyx b/fiona/ogrext.pyx
index 769c636..fb125c4 100644
--- a/fiona/ogrext.pyx
+++ b/fiona/ogrext.pyx
@@ -14,7 +14,7 @@ from fiona cimport ograpi
 from fiona._geometry cimport GeomBuilder, OGRGeomBuilder
 from fiona._err import cpl_errs
 from fiona._geometry import GEOMETRY_TYPES
-from fiona.errors import DriverError, SchemaError, CRSError
+from fiona.errors import DriverError, SchemaError, CRSError, FionaValueError
 from fiona.odict import OrderedDict
 from fiona.rfc3339 import parse_date, parse_datetime, parse_time
 from fiona.rfc3339 import FionaDateType, FionaDateTimeType, FionaTimeType
@@ -156,7 +156,7 @@ cdef class FeatureBuilder:
             if key_c == NULL:
                 raise ValueError("Null field name reference")
             key_b = key_c
-            key = key_b.decode('utf-8')
+            key = key_b.decode(encoding)
             fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(fdefn)]
             if not fieldtypename:
                 log.warn(
@@ -328,22 +328,22 @@ cdef class Session:
     cdef object _fileencoding
     cdef object _encoding
     cdef object collection
-    cdef int _read_ts
 
     def __cinit__(self):
         self.cogr_ds = NULL
         self.cogr_layer = NULL
         self._fileencoding = None
         self._encoding = None
-        self._read_ts = 0
 
     def __dealloc__(self):
         self.stop()
 
     def start(self, collection):
-        cdef char *path_c
-        cdef char *name_c
-        
+        cdef const char *path_c = NULL
+        cdef const char *name_c = NULL
+        cdef void *drv = NULL
+        cdef void *ds = NULL
+
         if collection.path == '-':
             path = '/vsistdin/'
         else:
@@ -356,10 +356,31 @@ cdef class Session:
         path_c = path_b
         
         with cpl_errs:
-            self.cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
+            drivers = []
+            if collection._driver:
+                drivers = [collection._driver]
+            elif collection.enabled_drivers:
+                drivers = collection.enabled_drivers
+            if drivers:
+                for name in drivers:
+                    name_b = name.encode()
+                    name_c = name_b
+                    log.debug("Trying driver: %s", name)
+                    drv = ograpi.OGRGetDriverByName(name_c)
+                    if drv != NULL:
+                        ds = ograpi.OGR_Dr_Open(drv, path_c, 0)
+                    if ds != NULL:
+                        self.cogr_ds = ds
+                        collection._driver = name
+                        break
+            else:
+                self.cogr_ds = ograpi.OGROpen(path_c, 0, NULL)
+
         if self.cogr_ds == NULL:
-            raise ValueError(
-                "No data available at path '%s'" % collection.path)
+            raise FionaValueError(
+                "No dataset found at path '%s' using drivers: %s" % (
+                    collection.path,
+                    drivers or '*'))
         
         if isinstance(collection.name, string_types):
             name_b = collection.name.encode('utf-8')
@@ -411,7 +432,6 @@ cdef class Session:
     def get_length(self):
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
-        self._read_ts += 1
         return ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
 
     def get_driver(self):
@@ -445,7 +465,7 @@ cdef class Session:
             key_b = key_c
             if not bool(key_b):
                 raise ValueError("Invalid field name ref: %s" % key)
-            key = key_b.decode('utf-8')
+            key = key_b.decode(self.get_internalencoding())
             fieldtypename = FIELD_TYPES[ograpi.OGR_Fld_GetType(cogr_fielddefn)]
             if not fieldtypename:
                 log.warn(
@@ -560,7 +580,6 @@ cdef class Session:
         if self.cogr_layer == NULL:
             raise ValueError("Null layer")
         cdef ograpi.OGREnvelope extent
-        self._read_ts += 1
         result = ograpi.OGR_L_GetExtent(self.cogr_layer, &extent, 1)
         return (extent.MinX, extent.MinY, extent.MaxX, extent.MaxY)
 
@@ -571,7 +590,6 @@ cdef class Session:
         """
         cdef void * cogr_feature
         fid = int(fid)
-        self._read_ts += 1
         cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
         if cogr_feature != NULL:
             _deleteOgrFeature(cogr_feature)
@@ -586,7 +604,6 @@ cdef class Session:
         """
         cdef void * cogr_feature
         fid = int(fid)
-        self._read_ts += 1
         cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, fid)
         if cogr_feature != NULL:
             _deleteOgrFeature(cogr_feature)
@@ -607,7 +624,8 @@ cdef class Session:
             if index < 0:
                 ftcount = ograpi.OGR_L_GetFeatureCount(self.cogr_layer, 0)
                 if ftcount == -1:
-                    raise RuntimeError("Layer does not support counting")
+                    raise IndexError(
+                        "collection's dataset does not support negative indexes")
                 index += ftcount
             cogr_feature = ograpi.OGR_L_GetFeature(self.cogr_layer, index)
             if cogr_feature == NULL:
@@ -928,7 +946,6 @@ cdef class Iterator:
     # Reference to its Collection
     cdef collection
     cdef encoding
-    cdef int _read_ts
     cdef int next_index
     cdef stop
     cdef start
@@ -965,15 +982,14 @@ cdef class Iterator:
                 cogr_layer, NULL)
         self.encoding = session.get_internalencoding()
 
-        session._read_ts += 1
-        self._read_ts = session._read_ts
-
         self.fastindex = ograpi.OGR_L_TestCapability(
             session.cogr_layer, OLC_FASTSETNEXTBYINDEX)
 
         ftcount = ograpi.OGR_L_GetFeatureCount(session.cogr_layer, 0)
-        if ftcount == -1:
-            raise RuntimeError("Layer does not support counting")
+        if ftcount == -1 and ((start is not None and start < 0) or
+                              (stop is not None and stop < 0)):
+            raise IndexError(
+                "collection's dataset does not support negative slice indexes")
 
         if stop is not None and stop < 0:
             stop += ftcount
@@ -1012,11 +1028,6 @@ cdef class Iterator:
         cdef Session session
         session = self.collection.session
 
-        if session._read_ts > self._read_ts:
-            warnings.warn("Read cursor may be altered. This can" \
-                         " lead to side effects", RuntimeWarning)
-
-
         # Check if next_index is valid
         if self.next_index < 0:
             raise StopIteration
@@ -1079,10 +1090,6 @@ cdef class ItemsIterator(Iterator):
         cdef Session session
         session = self.collection.session
 
-        if session._read_ts > self._read_ts:
-            warnings.warn("Read cursor may be altered. This can" \
-                         " lead to side effects", RuntimeWarning)
-
         #Update read cursor
         self._next()
 
@@ -1107,9 +1114,6 @@ cdef class KeysIterator(Iterator):
         cdef Session session
         session = self.collection.session
 
-        if session._read_ts > self._read_ts:
-            warnings.warn("Read cursor may be altered. This can" \
-                         " lead to side effects", RuntimeWarning)
         #Update read cursor
         self._next()
 
diff --git a/requirements.txt b/requirements.txt
index 7bb36c2..92e10dc 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
 argparse
-click
+cligj
 six
 ordereddict
diff --git a/setup.py b/setup.py
index 68c8241..02950da 100644
--- a/setup.py
+++ b/setup.py
@@ -1,14 +1,10 @@
 import logging
 import os
+import shutil
 import subprocess
 import sys
-
-try:
-    from setuptools import setup
-except ImportError:
-    from distutils.core import setup
-# Have to do this after importing setuptools, which monkey patches distutils.
-from distutils.extension import Extension
+from setuptools import setup
+from setuptools.extension import Extension
 
 # Use Cython if available.
 try:
@@ -19,6 +15,10 @@ except ImportError:
 logging.basicConfig()
 log = logging.getLogger()
 
+# python -W all setup.py ...
+if 'all' in sys.warnoptions:
+    log.level = logging.DEBUG
+
 # Parse the version from the fiona module.
 with open('fiona/__init__.py', 'r') as f:
     for line in f:
@@ -54,13 +54,15 @@ libraries = []
 extra_link_args = []
 
 try:
-    gdal_config = "gdal-config"
+    gdal_config = os.environ.get('GDAL_CONFIG', 'gdal-config')
     with open("gdal-config.txt", "w") as gcfg:
         subprocess.call([gdal_config, "--cflags"], stdout=gcfg)
         subprocess.call([gdal_config, "--libs"], stdout=gcfg)
+        subprocess.call([gdal_config, "--datadir"], stdout=gcfg)
     with open("gdal-config.txt", "r") as gcfg:
         cflags = gcfg.readline().strip()
         libs = gcfg.readline().strip()
+        datadir = gcfg.readline().strip()
     for item in cflags.split():
         if item.startswith("-I"):
             include_dirs.extend(item[2:].split(":"))
@@ -73,9 +75,28 @@ try:
             # e.g. -framework GDAL
             extra_link_args.append(item)
 
+    # Conditionally copy the GDAL data. To be used in conjunction with
+    # the bdist_wheel command to make self-contained binary wheels.
+    if os.environ.get('PACKAGE_DATA'):
+        try:
+            shutil.rmtree('fiona/gdal_data')
+        except OSError:
+            pass
+        shutil.copytree(datadir, 'fiona/gdal_data')
+
 except Exception as e:
     log.warning("Failed to get options via gdal-config: %s", str(e))
 
+# Conditionally copy PROJ.4 data.
+if os.environ.get('PACKAGE_DATA'):
+    projdatadir = os.environ.get('PROJ_LIB', '/usr/local/share/proj')
+    if os.path.exists(projdatadir):
+        try:
+            shutil.rmtree('fiona/proj_data')
+        except OSError:
+            pass
+        shutil.copytree(projdatadir, 'fiona/proj_data')
+
 ext_options = dict(
     include_dirs=include_dirs,
     library_dirs=library_dirs,
@@ -105,12 +126,12 @@ else:
         Extension('fiona._err', ['fiona/_err.c'], **ext_options),
         Extension('fiona.ogrext', ['fiona/ogrext.c'], **ext_options)]
 
-requirements = ['click', 'six']
+requirements = ['cligj', 'six']
 if sys.version_info < (2, 7):
     requirements.append('argparse')
     requirements.append('ordereddict')
 
-setup(
+setup_args = dict(
     metadata_version='1.2',
     name='Fiona',
     version=version,
@@ -144,5 +165,9 @@ setup(
         'Programming Language :: Python :: 2',
         'Programming Language :: Python :: 3',
         'Topic :: Scientific/Engineering :: GIS',
-    ],
-)
+    ])
+
+if os.environ.get('PACKAGE_DATA'):
+    setup_args['package_data'] = {'fiona': ['gdal_data/*', 'proj_data/*']}
+
+setup(**setup_args)
diff --git a/tests/__init__.py b/tests/__init__.py
index 0e6c3a8..b193a4c 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,7 +1,7 @@
 import os
 
-DATADIR = os.path.abspath('docs/data')
-FILES = ['test_uk.shp', 'test_uk.shx', 'test_uk.dbf', 'test_uk.prj']
+DATADIR = os.path.abspath('tests/data')
+FILES = ['coutwildrnp.shp', 'coutwildrnp.shx', 'coutwildrnp.dbf', 'coutwildrnp.prj']
 
 def create_zipfile(zipfilename):
     import zipfile
@@ -28,9 +28,9 @@ def create_jsonfile(jsonfilename):
 def setup():
     """Setup function for nosetests to create test files if they do not exist
     """
-    zipfile = os.path.join(DATADIR, 'test_uk.zip')
-    tarfile = os.path.join(DATADIR, 'test_uk.tar')
-    jsonfile = os.path.join(DATADIR, 'test_uk.json')
+    zipfile = os.path.join(DATADIR, 'coutwildrnp.zip')
+    tarfile = os.path.join(DATADIR, 'coutwildrnp.tar')
+    jsonfile = os.path.join(DATADIR, 'coutwildrnp.json')
     if not os.path.exists(zipfile):
         create_zipfile(zipfile)
     if not os.path.exists(tarfile):
diff --git a/tests/data/LICENSE.txt b/tests/data/LICENSE.txt
new file mode 100644
index 0000000..6adbde1
--- /dev/null
+++ b/tests/data/LICENSE.txt
@@ -0,0 +1,4 @@
+The coutwildrnp shapefile and all .txt files are extracts from the US National
+Map's 1:2M scale Wilderness Area boundaries [1] and are in the public domain.
+
+[1] http://nationalmap.gov/small_scale/atlasftp.html
diff --git a/tests/data/collection-pp.txt b/tests/data/collection-pp.txt
new file mode 100644
index 0000000..16521cc
--- /dev/null
+++ b/tests/data/collection-pp.txt
@@ -0,0 +1,635 @@
+
{
+  "type": "FeatureCollection",
+  "features": [
+    {
+      "geometry": {
+        "type": "Polygon",
+        "coordinates": [
+          [
+            [
+              -111.73527526855469,
+              41.995094299316406
+            ],
+            [
+              -111.65931701660156,
+              41.99627685546875
+            ],
+            [
+              -111.6587142944336,
+              41.9921875
+            ],
+            [
+              -111.65888977050781,
+              41.95676803588867
+            ],
+            [
+              -111.67082977294922,
+              41.91230010986328
+            ],
+            [
+              -111.67332458496094,
+              41.905494689941406
+            ],
+            [
+              -111.67088317871094,
+              41.90049362182617
+            ],
+            [
+              -111.66474914550781,
+              41.893211364746094
+            ],
+            [
+              -111.6506576538086,
+              41.875465393066406
+            ],
+            [
+              -111.64759826660156,
+              41.87091827392578
+            ],
+            [
+              -111.64640808105469,
+              41.86273956298828
+            ],
+            [
+              -111.64334869384766,
+              41.858192443847656
+            ],
+            [
+              -111.63720703125,
+              41.85499572753906
+            ],
+            [
+              -111.633544921875,
+              41.847267150878906
+            ],
+            [
+              -111.63053894042969,
+              41.83409118652344
+            ],
+            [
+              -111.6330337524414,
+              41.82728576660156
+            ],
+            [
+              -111.63983154296875,
+              41.8227653503418
+            ],
+            [
+              -111.6484603881836,
+              41.82188034057617
+            ],
+            [
+              -111.66077423095703,
+              41.82327651977539
+            ],
+            [
+              -111.6712417602539,
+              41.82330322265625
+            ],
+            [
+              -111.67618560791016,
+              41.82013702392578
+            ],
+            [
+              -111.68803405761719,
+              41.78792953491211
+            ],
+            [
+              -111.69361114501953,
+              41.77931594848633
+            ],
+            [
+              -111.70162200927734,
+              41.77797317504883
+            ],
+            [
+              -111.70901489257812,
+              41.77663040161133
+            ],
+            [
+              -111.71395111083984,
+              41.772098541259766
+            ],
+            [
+              -111.71891784667969,
+              41.763031005859375
+            ],
+            [
+              -111.72816467285156,
+              41.75851058959961
+            ],
+            [
+              -111.74726104736328,
+              41.75537109375
+            ],
+            [
+              -111.75650024414062,
+              41.752662658691406
+            ],
+            [
+              -111.77067565917969,
+              41.7445182800293
+            ],
+            [
+              -111.77064514160156,
+              41.75495910644531
+            ],
+            [
+              -111.75585174560547,
+              41.76219940185547
+            ],
+            [
+              -111.7330551147461,
+              41.766693115234375
+            ],
+            [
+              -111.72749328613281,
+              41.77212905883789
+            ],
+            [
+              -111.71883392333984,
+              41.7834587097168
+            ],
+            [
+              -111.71080780029297,
+              41.78889083862305
+            ],
+            [
+              -111.70340728759766,
+              41.79250717163086
+            ],
+            [
+              -111.70030212402344,
+              41.798404693603516
+            ],
+            [
+              -111.70210266113281,
+              41.8088493347168
+            ],
+            [
+              -111.70760345458984,
+              41.819759368896484
+            ],
+            [
+              -111.71312713623047,
+              41.82340621948242
+            ],
+            [
+              -111.71929168701172,
+              41.82341766357422
+            ],
+            [
+              -111.72545623779297,
+              41.8225212097168
+            ],
+            [
+              -111.7341537475586,
+              41.803016662597656
+            ],
+            [
+              -111.740966796875,
+              41.79213333129883
+            ],
+            [
+              -111.74531555175781,
+              41.78215408325195
+            ],
+            [
+              -111.77122497558594,
+              41.7658576965332
+            ],
+            [
+              -111.77056884765625,
+              41.77811813354492
+            ],
+            [
+              -111.7662582397461,
+              41.778106689453125
+            ],
+            [
+              -111.76746368408203,
+              41.78628158569336
+            ],
+            [
+              -111.76253509521484,
+              41.78627395629883
+            ],
+            [
+              -111.76241302490234,
+              41.82259750366211
+            ],
+            [
+              -111.77104187011719,
+              41.8221549987793
+            ],
+            [
+              -111.77161407470703,
+              41.83351135253906
+            ],
+            [
+              -111.7333755493164,
+              41.84524154663086
+            ],
+            [
+              -111.73274993896484,
+              41.847511291503906
+            ],
+            [
+              -111.7376708984375,
+              41.84979248046875
+            ],
+            [
+              -111.77157592773438,
+              41.845767974853516
+            ],
+            [
+              -111.77215576171875,
+              41.85802459716797
+            ],
+            [
+              -111.75243377685547,
+              41.85844802856445
+            ],
+            [
+              -111.72467803955078,
+              41.86384201049805
+            ],
+            [
+              -111.71109771728516,
+              41.868804931640625
+            ],
+            [
+              -111.70182037353516,
+              41.87604904174805
+            ],
+            [
+              -111.69624328613281,
+              41.88193893432617
+            ],
+            [
+              -111.69497680664062,
+              41.88874816894531
+            ],
+            [
+              -111.70053100585938,
+              41.89057540893555
+            ],
+            [
+              -111.70793151855469,
+              41.88923263549805
+            ],
+            [
+              -111.72091674804688,
+              41.87972640991211
+            ],
+            [
+              -111.73388671875,
+              41.87384796142578
+            ],
+            [
+              -111.75301361083984,
+              41.86888885498047
+            ],
+            [
+              -111.75350952148438,
+              41.90249252319336
+            ],
+            [
+              -111.74364471435547,
+              41.90247344970703
+            ],
+            [
+              -111.74463653564453,
+              41.967864990234375
+            ],
+            [
+              -111.7119369506836,
+              41.96416473388672
+            ],
+            [
+              -111.69283294677734,
+              41.95912551879883
+            ],
+            [
+              -111.68911743164062,
+              41.96047592163086
+            ],
+            [
+              -111.6891098022461,
+              41.96320343017578
+            ],
+            [
+              -111.69341278076172,
+              41.96684646606445
+            ],
+            [
+              -111.70449829101562,
+              41.972320556640625
+            ],
+            [
+              -111.7341079711914,
+              41.97828674316406
+            ],
+            [
+              -111.73527526855469,
+              41.995094299316406
+            ]
+          ]
+        ]
+      },
+      "type": "Feature",
+      "id": "0",
+      "properties": {
+        "PERIMETER": 1.22107,
+        "FEATURE2": null,
+        "NAME": "Mount Naomi Wilderness",
+        "FEATURE1": "Wilderness",
+        "URL": "http://www.wilderness.net/index.cfm?fuse=NWPS&sec=wildView&wname=Mount%20Naomi",
+        "AGBUR": "FS",
+        "AREA": 0.0179264,
+        "STATE_FIPS": "49",
+        "WILDRNP020": 332,
+        "STATE": "UT"
+      }
+    },
+    {
+      "geometry": {
+        "type": "Polygon",
+        "coordinates": [
+          [
+            [
+              -112.00384521484375,
+              41.552703857421875
+            ],
+            [
+              -112.00446319580078,
+              41.56586456298828
+            ],
+            [
+              -112.0112075805664,
+              41.56586456298828
+            ],
+            [
+              -112.01121520996094,
+              41.57902526855469
+            ],
+            [
+              -112.01734924316406,
+              41.57902526855469
+            ],
+            [
+              -112.0173568725586,
+              41.594459533691406
+            ],
+            [
+              -112.02779388427734,
+              41.5940055847168
+            ],
+            [
+              -112.02779388427734,
+              41.60171890258789
+            ],
+            [
+              -112.03945922851562,
+              41.60126495361328
+            ],
+            [
+              -112.04007720947266,
+              41.608524322509766
+            ],
+            [
+              -112.04744720458984,
+              41.608524322509766
+            ],
+            [
+              -112.0474624633789,
+              41.62804412841797
+            ],
+            [
+              -112.05974578857422,
+              41.62758255004883
+            ],
+            [
+              -112.05975341796875,
+              41.640296936035156
+            ],
+            [
+              -112.050537109375,
+              41.64030075073242
+            ],
+            [
+              -112.05054473876953,
+              41.64983367919922
+            ],
+            [
+              -112.04132843017578,
+              41.64983367919922
+            ],
+            [
+              -112.04195404052734,
+              41.66299819946289
+            ],
+            [
+              -112.05793762207031,
+              41.662540435791016
+            ],
+            [
+              -112.0579605102539,
+              41.692047119140625
+            ],
+            [
+              -112.07394409179688,
+              41.692039489746094
+            ],
+            [
+              -112.07459259033203,
+              41.72381591796875
+            ],
+            [
+              -112.06167602539062,
+              41.72382354736328
+            ],
+            [
+              -112.0616683959961,
+              41.71383285522461
+            ],
+            [
+              -112.05490112304688,
+              41.713836669921875
+            ],
+            [
+              -112.04137420654297,
+              41.71384048461914
+            ],
+            [
+              -112.04138946533203,
+              41.7379035949707
+            ],
+            [
+              -112.0376968383789,
+              41.74108123779297
+            ],
+            [
+              -112.03339385986328,
+              41.741085052490234
+            ],
+            [
+              -112.02908325195312,
+              41.729736328125
+            ],
+            [
+              -112.02599334716797,
+              41.71657180786133
+            ],
+            [
+              -112.0241470336914,
+              41.71157455444336
+            ],
+            [
+              -112.0272216796875,
+              41.704769134521484
+            ],
+            [
+              -112.02413940429688,
+              41.70068359375
+            ],
+            [
+              -112.01676177978516,
+              41.69977951049805
+            ],
+            [
+              -112.01615142822266,
+              41.7070426940918
+            ],
+            [
+              -112.00508117675781,
+              41.707496643066406
+            ],
+            [
+              -112.00508117675781,
+              41.66618347167969
+            ],
+            [
+              -111.9792709350586,
+              41.6666374206543
+            ],
+            [
+              -111.9786605834961,
+              41.653926849365234
+            ],
+            [
+              -111.96821594238281,
+              41.65346908569336
+            ],
+            [
+              -111.96760559082031,
+              41.6407585144043
+            ],
+            [
+              -111.96146392822266,
+              41.6407585144043
+            ],
+            [
+              -111.96025085449219,
+              41.61125183105469
+            ],
+            [
+              -111.95042419433594,
+              41.61124801635742
+            ],
+            [
+              -111.94796752929688,
+              41.60988235473633
+            ],
+            [
+              -111.94735717773438,
+              41.60761260986328
+            ],
+            [
+              -111.9522705078125,
+              41.60443878173828
+            ],
+            [
+              -111.96455383300781,
+              41.60262680053711
+            ],
+            [
+              -111.9682388305664,
+              41.60398864746094
+            ],
+            [
+              -111.9725341796875,
+              41.60807418823242
+            ],
+            [
+              -111.97560119628906,
+              41.60943603515625
+            ],
+            [
+              -111.97928619384766,
+              41.61034393310547
+            ],
+            [
+              -111.98542785644531,
+              41.609439849853516
+            ],
+            [
+              -111.98481750488281,
+              41.58356475830078
+            ],
+            [
+              -111.97868347167969,
+              41.58356857299805
+            ],
+            [
+              -111.97745513916016,
+              41.570404052734375
+            ],
+            [
+              -111.97132110595703,
+              41.57085418701172
+            ],
+            [
+              -111.97132110595703,
+              41.56450271606445
+            ],
+            [
+              -111.98297882080078,
+              41.564048767089844
+            ],
+            [
+              -111.98175811767578,
+              41.54090118408203
+            ],
+            [
+              -111.98176574707031,
+              41.53545379638672
+            ],
+            [
+              -112.00323486328125,
+              41.53545379638672
+            ],
+            [
+              -112.00384521484375,
+              41.552703857421875
+            ]
+          ]
+        ]
+      },
+      "type": "Feature",
+      "id": "1",
+      "properties": {
+        "PERIMETER": 0.755827,
+        "FEATURE2": null,
+        "NAME": "Wellsville Mountain Wilderness",
+        "FEATURE1": "Wilderness",
+        "URL": "http://www.wilderness.net/index.cfm?fuse=NWPS&sec=wildView&wname=Wellsville%20Mountain",
+        "AGBUR": "FS",
+        "AREA": 0.0104441,
+        "STATE_FIPS": "49",
+        "WILDRNP020": 336,
+        "STATE": "UT"
+      }
+    }
+  ]
+}
diff --git a/tests/data/collection.txt b/tests/data/collection.txt
new file mode 100644
index 0000000..e5cf837
--- /dev/null
+++ b/tests/data/collection.txt
@@ -0,0 +1 @@
+{"type": "FeatureCollection", "features": [{"geometry": {"type": "Polygon", "coordinates": [[[-111.73527526855469, 41.995094299316406], [-111.65931701660156, 41.99627685546875], [-111.6587142944336, 41.9921875], [-111.65888977050781, 41.95676803588867], [-111.67082977294922, 41.91230010986328], [-111.67332458496094, 41.905494689941406], [-111.67088317871094, 41.90049362182617], [-111.66474914550781, 41.893211364746094], [-111.6506576538086, 41.875465393066406], [-111.64759826660156, 41.8 [...]
\ No newline at end of file
diff --git a/tests/data/coutwildrnp.dbf b/tests/data/coutwildrnp.dbf
new file mode 100644
index 0000000..441c14e
Binary files /dev/null and b/tests/data/coutwildrnp.dbf differ
diff --git a/docs/data/test_uk.prj b/tests/data/coutwildrnp.prj
similarity index 100%
rename from docs/data/test_uk.prj
rename to tests/data/coutwildrnp.prj
diff --git a/tests/data/coutwildrnp.shp b/tests/data/coutwildrnp.shp
new file mode 100644
index 0000000..f1f62b5
Binary files /dev/null and b/tests/data/coutwildrnp.shp differ
diff --git a/tests/data/coutwildrnp.shx b/tests/data/coutwildrnp.shx
new file mode 100644
index 0000000..7eae700
Binary files /dev/null and b/tests/data/coutwildrnp.shx differ
diff --git a/tests/data/sequence-pp.txt b/tests/data/sequence-pp.txt
new file mode 100644
index 0000000..085dd1f
--- /dev/null
+++ b/tests/data/sequence-pp.txt
@@ -0,0 +1,630 @@
+
{
+  "geometry": {
+    "type": "Polygon", 
+    "coordinates": [
+      [
+        [
+          -111.73527526855469, 
+          41.995094299316406
+        ], 
+        [
+          -111.65931701660156, 
+          41.99627685546875
+        ], 
+        [
+          -111.6587142944336, 
+          41.9921875
+        ], 
+        [
+          -111.65888977050781, 
+          41.95676803588867
+        ], 
+        [
+          -111.67082977294922, 
+          41.91230010986328
+        ], 
+        [
+          -111.67332458496094, 
+          41.905494689941406
+        ], 
+        [
+          -111.67088317871094, 
+          41.90049362182617
+        ], 
+        [
+          -111.66474914550781, 
+          41.893211364746094
+        ], 
+        [
+          -111.6506576538086, 
+          41.875465393066406
+        ], 
+        [
+          -111.64759826660156, 
+          41.87091827392578
+        ], 
+        [
+          -111.64640808105469, 
+          41.86273956298828
+        ], 
+        [
+          -111.64334869384766, 
+          41.858192443847656
+        ], 
+        [
+          -111.63720703125, 
+          41.85499572753906
+        ], 
+        [
+          -111.633544921875, 
+          41.847267150878906
+        ], 
+        [
+          -111.63053894042969, 
+          41.83409118652344
+        ], 
+        [
+          -111.6330337524414, 
+          41.82728576660156
+        ], 
+        [
+          -111.63983154296875, 
+          41.8227653503418
+        ], 
+        [
+          -111.6484603881836, 
+          41.82188034057617
+        ], 
+        [
+          -111.66077423095703, 
+          41.82327651977539
+        ], 
+        [
+          -111.6712417602539, 
+          41.82330322265625
+        ], 
+        [
+          -111.67618560791016, 
+          41.82013702392578
+        ], 
+        [
+          -111.68803405761719, 
+          41.78792953491211
+        ], 
+        [
+          -111.69361114501953, 
+          41.77931594848633
+        ], 
+        [
+          -111.70162200927734, 
+          41.77797317504883
+        ], 
+        [
+          -111.70901489257812, 
+          41.77663040161133
+        ], 
+        [
+          -111.71395111083984, 
+          41.772098541259766
+        ], 
+        [
+          -111.71891784667969, 
+          41.763031005859375
+        ], 
+        [
+          -111.72816467285156, 
+          41.75851058959961
+        ], 
+        [
+          -111.74726104736328, 
+          41.75537109375
+        ], 
+        [
+          -111.75650024414062, 
+          41.752662658691406
+        ], 
+        [
+          -111.77067565917969, 
+          41.7445182800293
+        ], 
+        [
+          -111.77064514160156, 
+          41.75495910644531
+        ], 
+        [
+          -111.75585174560547, 
+          41.76219940185547
+        ], 
+        [
+          -111.7330551147461, 
+          41.766693115234375
+        ], 
+        [
+          -111.72749328613281, 
+          41.77212905883789
+        ], 
+        [
+          -111.71883392333984, 
+          41.7834587097168
+        ], 
+        [
+          -111.71080780029297, 
+          41.78889083862305
+        ], 
+        [
+          -111.70340728759766, 
+          41.79250717163086
+        ], 
+        [
+          -111.70030212402344, 
+          41.798404693603516
+        ], 
+        [
+          -111.70210266113281, 
+          41.8088493347168
+        ], 
+        [
+          -111.70760345458984, 
+          41.819759368896484
+        ], 
+        [
+          -111.71312713623047, 
+          41.82340621948242
+        ], 
+        [
+          -111.71929168701172, 
+          41.82341766357422
+        ], 
+        [
+          -111.72545623779297, 
+          41.8225212097168
+        ], 
+        [
+          -111.7341537475586, 
+          41.803016662597656
+        ], 
+        [
+          -111.740966796875, 
+          41.79213333129883
+        ], 
+        [
+          -111.74531555175781, 
+          41.78215408325195
+        ], 
+        [
+          -111.77122497558594, 
+          41.7658576965332
+        ], 
+        [
+          -111.77056884765625, 
+          41.77811813354492
+        ], 
+        [
+          -111.7662582397461, 
+          41.778106689453125
+        ], 
+        [
+          -111.76746368408203, 
+          41.78628158569336
+        ], 
+        [
+          -111.76253509521484, 
+          41.78627395629883
+        ], 
+        [
+          -111.76241302490234, 
+          41.82259750366211
+        ], 
+        [
+          -111.77104187011719, 
+          41.8221549987793
+        ], 
+        [
+          -111.77161407470703, 
+          41.83351135253906
+        ], 
+        [
+          -111.7333755493164, 
+          41.84524154663086
+        ], 
+        [
+          -111.73274993896484, 
+          41.847511291503906
+        ], 
+        [
+          -111.7376708984375, 
+          41.84979248046875
+        ], 
+        [
+          -111.77157592773438, 
+          41.845767974853516
+        ], 
+        [
+          -111.77215576171875, 
+          41.85802459716797
+        ], 
+        [
+          -111.75243377685547, 
+          41.85844802856445
+        ], 
+        [
+          -111.72467803955078, 
+          41.86384201049805
+        ], 
+        [
+          -111.71109771728516, 
+          41.868804931640625
+        ], 
+        [
+          -111.70182037353516, 
+          41.87604904174805
+        ], 
+        [
+          -111.69624328613281, 
+          41.88193893432617
+        ], 
+        [
+          -111.69497680664062, 
+          41.88874816894531
+        ], 
+        [
+          -111.70053100585938, 
+          41.89057540893555
+        ], 
+        [
+          -111.70793151855469, 
+          41.88923263549805
+        ], 
+        [
+          -111.72091674804688, 
+          41.87972640991211
+        ], 
+        [
+          -111.73388671875, 
+          41.87384796142578
+        ], 
+        [
+          -111.75301361083984, 
+          41.86888885498047
+        ], 
+        [
+          -111.75350952148438, 
+          41.90249252319336
+        ], 
+        [
+          -111.74364471435547, 
+          41.90247344970703
+        ], 
+        [
+          -111.74463653564453, 
+          41.967864990234375
+        ], 
+        [
+          -111.7119369506836, 
+          41.96416473388672
+        ], 
+        [
+          -111.69283294677734, 
+          41.95912551879883
+        ], 
+        [
+          -111.68911743164062, 
+          41.96047592163086
+        ], 
+        [
+          -111.6891098022461, 
+          41.96320343017578
+        ], 
+        [
+          -111.69341278076172, 
+          41.96684646606445
+        ], 
+        [
+          -111.70449829101562, 
+          41.972320556640625
+        ], 
+        [
+          -111.7341079711914, 
+          41.97828674316406
+        ], 
+        [
+          -111.73527526855469, 
+          41.995094299316406
+        ]
+      ]
+    ]
+  }, 
+  "type": "Feature", 
+  "id": "0", 
+  "properties": {
+    "PERIMETER": 1.22107, 
+    "FEATURE2": null, 
+    "NAME": "Mount Naomi Wilderness", 
+    "FEATURE1": "Wilderness", 
+    "URL": "http://www.wilderness.net/index.cfm?fuse=NWPS&sec=wildView&wname=Mount%20Naomi", 
+    "AGBUR": "FS", 
+    "AREA": 0.0179264, 
+    "STATE_FIPS": "49", 
+    "WILDRNP020": 332, 
+    "STATE": "UT"
+  }
+}
+
{
+  "geometry": {
+    "type": "Polygon", 
+    "coordinates": [
+      [
+        [
+          -112.00384521484375, 
+          41.552703857421875
+        ], 
+        [
+          -112.00446319580078, 
+          41.56586456298828
+        ], 
+        [
+          -112.0112075805664, 
+          41.56586456298828
+        ], 
+        [
+          -112.01121520996094, 
+          41.57902526855469
+        ], 
+        [
+          -112.01734924316406, 
+          41.57902526855469
+        ], 
+        [
+          -112.0173568725586, 
+          41.594459533691406
+        ], 
+        [
+          -112.02779388427734, 
+          41.5940055847168
+        ], 
+        [
+          -112.02779388427734, 
+          41.60171890258789
+        ], 
+        [
+          -112.03945922851562, 
+          41.60126495361328
+        ], 
+        [
+          -112.04007720947266, 
+          41.608524322509766
+        ], 
+        [
+          -112.04744720458984, 
+          41.608524322509766
+        ], 
+        [
+          -112.0474624633789, 
+          41.62804412841797
+        ], 
+        [
+          -112.05974578857422, 
+          41.62758255004883
+        ], 
+        [
+          -112.05975341796875, 
+          41.640296936035156
+        ], 
+        [
+          -112.050537109375, 
+          41.64030075073242
+        ], 
+        [
+          -112.05054473876953, 
+          41.64983367919922
+        ], 
+        [
+          -112.04132843017578, 
+          41.64983367919922
+        ], 
+        [
+          -112.04195404052734, 
+          41.66299819946289
+        ], 
+        [
+          -112.05793762207031, 
+          41.662540435791016
+        ], 
+        [
+          -112.0579605102539, 
+          41.692047119140625
+        ], 
+        [
+          -112.07394409179688, 
+          41.692039489746094
+        ], 
+        [
+          -112.07459259033203, 
+          41.72381591796875
+        ], 
+        [
+          -112.06167602539062, 
+          41.72382354736328
+        ], 
+        [
+          -112.0616683959961, 
+          41.71383285522461
+        ], 
+        [
+          -112.05490112304688, 
+          41.713836669921875
+        ], 
+        [
+          -112.04137420654297, 
+          41.71384048461914
+        ], 
+        [
+          -112.04138946533203, 
+          41.7379035949707
+        ], 
+        [
+          -112.0376968383789, 
+          41.74108123779297
+        ], 
+        [
+          -112.03339385986328, 
+          41.741085052490234
+        ], 
+        [
+          -112.02908325195312, 
+          41.729736328125
+        ], 
+        [
+          -112.02599334716797, 
+          41.71657180786133
+        ], 
+        [
+          -112.0241470336914, 
+          41.71157455444336
+        ], 
+        [
+          -112.0272216796875, 
+          41.704769134521484
+        ], 
+        [
+          -112.02413940429688, 
+          41.70068359375
+        ], 
+        [
+          -112.01676177978516, 
+          41.69977951049805
+        ], 
+        [
+          -112.01615142822266, 
+          41.7070426940918
+        ], 
+        [
+          -112.00508117675781, 
+          41.707496643066406
+        ], 
+        [
+          -112.00508117675781, 
+          41.66618347167969
+        ], 
+        [
+          -111.9792709350586, 
+          41.6666374206543
+        ], 
+        [
+          -111.9786605834961, 
+          41.653926849365234
+        ], 
+        [
+          -111.96821594238281, 
+          41.65346908569336
+        ], 
+        [
+          -111.96760559082031, 
+          41.6407585144043
+        ], 
+        [
+          -111.96146392822266, 
+          41.6407585144043
+        ], 
+        [
+          -111.96025085449219, 
+          41.61125183105469
+        ], 
+        [
+          -111.95042419433594, 
+          41.61124801635742
+        ], 
+        [
+          -111.94796752929688, 
+          41.60988235473633
+        ], 
+        [
+          -111.94735717773438, 
+          41.60761260986328
+        ], 
+        [
+          -111.9522705078125, 
+          41.60443878173828
+        ], 
+        [
+          -111.96455383300781, 
+          41.60262680053711
+        ], 
+        [
+          -111.9682388305664, 
+          41.60398864746094
+        ], 
+        [
+          -111.9725341796875, 
+          41.60807418823242
+        ], 
+        [
+          -111.97560119628906, 
+          41.60943603515625
+        ], 
+        [
+          -111.97928619384766, 
+          41.61034393310547
+        ], 
+        [
+          -111.98542785644531, 
+          41.609439849853516
+        ], 
+        [
+          -111.98481750488281, 
+          41.58356475830078
+        ], 
+        [
+          -111.97868347167969, 
+          41.58356857299805
+        ], 
+        [
+          -111.97745513916016, 
+          41.570404052734375
+        ], 
+        [
+          -111.97132110595703, 
+          41.57085418701172
+        ], 
+        [
+          -111.97132110595703, 
+          41.56450271606445
+        ], 
+        [
+          -111.98297882080078, 
+          41.564048767089844
+        ], 
+        [
+          -111.98175811767578, 
+          41.54090118408203
+        ], 
+        [
+          -111.98176574707031, 
+          41.53545379638672
+        ], 
+        [
+          -112.00323486328125, 
+          41.53545379638672
+        ], 
+        [
+          -112.00384521484375, 
+          41.552703857421875
+        ]
+      ]
+    ]
+  }, 
+  "type": "Feature", 
+  "id": "1", 
+  "properties": {
+    "PERIMETER": 0.755827, 
+    "FEATURE2": null, 
+    "NAME": "Wellsville Mountain Wilderness", 
+    "FEATURE1": "Wilderness", 
+    "URL": "http://www.wilderness.net/index.cfm?fuse=NWPS&sec=wildView&wname=Wellsville%20Mountain", 
+    "AGBUR": "FS", 
+    "AREA": 0.0104441, 
+    "STATE_FIPS": "49", 
+    "WILDRNP020": 336, 
+    "STATE": "UT"
+  }
+}
diff --git a/tests/data/sequence.txt b/tests/data/sequence.txt
new file mode 100644
index 0000000..4bfd03e
--- /dev/null
+++ b/tests/data/sequence.txt
@@ -0,0 +1,2 @@
+{"geometry": {"type": "Polygon", "coordinates": [[[-111.73527526855469, 41.995094299316406], [-111.65931701660156, 41.99627685546875], [-111.6587142944336, 41.9921875], [-111.65888977050781, 41.95676803588867], [-111.67082977294922, 41.91230010986328], [-111.67332458496094, 41.905494689941406], [-111.67088317871094, 41.90049362182617], [-111.66474914550781, 41.893211364746094], [-111.6506576538086, 41.875465393066406], [-111.64759826660156, 41.87091827392578], [-111.64640808105469, 41.86 [...]
+{"geometry": {"type": "Polygon", "coordinates": [[[-112.00384521484375, 41.552703857421875], [-112.00446319580078, 41.56586456298828], [-112.0112075805664, 41.56586456298828], [-112.01121520996094, 41.57902526855469], [-112.01734924316406, 41.57902526855469], [-112.0173568725586, 41.594459533691406], [-112.02779388427734, 41.5940055847168], [-112.02779388427734, 41.60171890258789], [-112.03945922851562, 41.60126495361328], [-112.04007720947266, 41.608524322509766], [-112.04744720458984,  [...]
diff --git a/tests/data/test_gpx.gpx b/tests/data/test_gpx.gpx
new file mode 100644
index 0000000..24d9ef0
--- /dev/null
+++ b/tests/data/test_gpx.gpx
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx
+  version="1.1"
+  creator="RunKeeper - http://www.runkeeper.com"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://www.topografix.com/GPX/1/1"
+  xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
+  xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1">
+<trk>
+  <name><![CDATA[Running 6/11/14 8:19 am]]></name>
+  <time>2014-06-11T12:19:43Z</time>
+<trkseg>
+<trkpt lat="42.361951000" lon="-71.108203000"><ele>11.0</ele><time>2014-06-11T12:21:40Z</time></trkpt>
+<trkpt lat="42.361797000" lon="-71.108370000"><ele>10.9</ele><time>2014-06-11T12:21:48Z</time></trkpt>
+<trkpt lat="42.361615000" lon="-71.108543000"><ele>10.7</ele><time>2014-06-11T12:21:56Z</time></trkpt>
+<trkpt lat="42.361451000" lon="-71.108731000"><ele>10.5</ele><time>2014-06-11T12:22:04Z</time></trkpt>
+<trkpt lat="42.361341000" lon="-71.108968000"><ele>10.4</ele><time>2014-06-11T12:22:12Z</time></trkpt>
+<trkpt lat="42.361474000" lon="-71.109162000"><ele>10.2</ele><time>2014-06-11T12:22:20Z</time></trkpt>
+<trkpt lat="42.361612000" lon="-71.109330000"><ele>10.0</ele><time>2014-06-11T12:22:27Z</time></trkpt>
+<trkpt lat="42.361751000" lon="-71.109529000"><ele>10.0</ele><time>2014-06-11T12:22:36Z</time></trkpt>
+<trkpt lat="42.361880000" lon="-71.109774000"><ele>10.0</ele><time>2014-06-11T12:22:43Z</time></trkpt>
+<trkpt lat="42.362007000" lon="-71.109991000"><ele>10.2</ele><time>2014-06-11T12:22:53Z</time></trkpt>
+<trkpt lat="42.362115000" lon="-71.110213000"><ele>10.4</ele><time>2014-06-11T12:23:01Z</time></trkpt>
+<trkpt lat="42.362180000" lon="-71.110484000"><ele>10.5</ele><time>2014-06-11T12:23:09Z</time></trkpt>
+<trkpt lat="42.362205000" lon="-71.110728000"><ele>10.5</ele><time>2014-06-11T12:23:18Z</time></trkpt>
+<trkpt lat="42.362320000" lon="-71.110988000"><ele>10.1</ele><time>2014-06-11T12:23:27Z</time></trkpt>
+<trkpt lat="42.362467000" lon="-71.111170000"><ele>9.6</ele><time>2014-06-11T12:23:34Z</time></trkpt>
+<trkpt lat="42.362640000" lon="-71.111344000"><ele>9.1</ele><time>2014-06-11T12:23:42Z</time></trkpt>
+<trkpt lat="42.362799000" lon="-71.111519000"><ele>8.3</ele><time>2014-06-11T12:23:51Z</time></trkpt>
+<trkpt lat="42.362837000" lon="-71.111772000"><ele>7.2</ele><time>2014-06-11T12:23:57Z</time></trkpt>
+<trkpt lat="42.362716000" lon="-71.111994000"><ele>6.6</ele><time>2014-06-11T12:24:04Z</time></trkpt>
+</trkseg>
+</trk>
+</gpx>
diff --git a/tests/fixtures.py b/tests/fixtures.py
new file mode 100644
index 0000000..1a38cab
--- /dev/null
+++ b/tests/fixtures.py
@@ -0,0 +1,10 @@
+import os.path
+
+
+def read_file(name):
+    return open(os.path.join(os.path.dirname(__file__), name)).read()
+
+feature_collection = read_file('data/collection.txt')
+feature_collection_pp = read_file('data/collection-pp.txt')
+feature_seq = read_file('data/sequence.txt')
+feature_seq_pp_rs = read_file('data/sequence-pp.txt')
diff --git a/tests/test_bounds.py b/tests/test_bounds.py
index 420f5e2..5d93d71 100644
--- a/tests/test_bounds.py
+++ b/tests/test_bounds.py
@@ -1,18 +1,20 @@
 import fiona
 
-def test_bounds():
-    with fiona.open("docs/data/test_uk.shp") as src:
-        f = next(src)
-        assert tuple(round(v, 6) for v in fiona.bounds(f)) == (
-                                                         0.735,
-                                                         51.357216,
-                                                         0.947778,
-                                                         51.444717)
-        assert tuple(round(v, 6) for v in fiona.bounds(f['geometry'])) == (
-                                                         0.735,
-                                                         51.357216,
-                                                         0.947778,
-                                                         51.444717)
+
+def test_bounds_point():
+    g = {'type': 'Point', 'coordinates': [10, 10]}
+    assert fiona.bounds(g) == (10, 10, 10, 10)
+
+
+def test_bounds_line():
+    g = {'type': 'LineString', 'coordinates': [[0, 0], [10, 10]]}
+    assert fiona.bounds(g) == (0, 0, 10, 10)
+
+
+def test_bounds_polygon():
+    g = {'type': 'Polygon', 'coordinates': [[[0, 0], [10, 10], [10, 0]]]}
+    assert fiona.bounds(g) == (0, 0, 10, 10)
+
 
 def test_bounds_z():
     g = {'type': 'Point', 'coordinates': [10,10,10]}
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 682cd61..0a9bfb1 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1,80 +1,33 @@
 import json
-import subprocess
+import re
 
+import click
+from click.testing import CliRunner
 
-def test_cli_info_json():
-    result = subprocess.check_output(
-        'fio info docs/data/test_uk.shp',
-        shell=True)
-    text = result.decode('utf-8').strip()
-    assert json.loads(text)['count'] == 48
+from fiona.fio import fio
 
 
-def test_cli_info_count():
-    result = subprocess.check_output(
-        'fio info docs/data/test_uk.shp --count',
-        shell=True)
-    assert result.decode('utf-8').strip() == '48'
+WILDSHP = 'tests/data/coutwildrnp.shp'
 
 
-def test_cli_info_bounds():
-    result = subprocess.check_output(
-        'fio info docs/data/test_uk.shp --bounds',
-        shell=True)
-    assert result.decode('utf-8').strip() == (
-        '-8.621389 49.911659 1.749444 60.844444')
+def test_info_json():
+    runner = CliRunner()
+    result = runner.invoke(fio.info, [WILDSHP])
+    assert result.exit_code == 0
+    assert '"count": 67' in result.output
+    assert '"crs": "EPSG:4326"' in result.output
+    assert '"driver": "ESRI Shapefile"' in result.output
 
 
-def test_cli_cat():
-    result = subprocess.check_output(
-        'fio cat docs/data/test_uk.shp docs/data/test_uk.shp',
-        shell=True)
-    records = result.decode('utf-8').strip().split('\n')
-    assert len(records) == 96
-    for record in records:
-        assert json.loads(record.strip())['type'] == 'Feature'
+def test_info_count():
+    runner = CliRunner()
+    result = runner.invoke(fio.info, ['--count', WILDSHP])
+    assert result.exit_code == 0
+    assert result.output == "67\n"
 
 
-def test_cli_cat_rs():
-    result = subprocess.check_output(
-        'fio cat docs/data/test_uk.shp docs/data/test_uk.shp '
-        '--indent 2 --x-json-seq-rs',
-        shell=True)
-    texts = result.decode('utf-8').split(u'\x1e')
-    assert len(texts) == 97
-    assert texts[0] == ''
-    for text in texts:
-        if not text:
-            continue
-        assert json.loads(text)['type'] == 'Feature'
-
-
-def test_cli_collect():
-    feature = {
-        'type': 'Feature',
-        'properties': {},
-        'geometry': {
-            'type': 'Point',
-            'coordinates': [0.0, 0.0] }}
-    result = subprocess.check_output(
-        "echo '%s' | fio collect" % json.dumps(feature),
-        shell=True)
-    collection = json.loads(result.decode('utf-8'))
-    assert len(collection['features']) == 1
-    assert collection['features'][0] == feature
-
-
-def test_cli_collect_rs():
-    feature = {
-        'type': 'Feature',
-        'properties': {},
-        'geometry': {
-            'type': 'Point',
-            'coordinates': [0.0, 0.0] }}
-    result = subprocess.check_output(
-        "printf '\036%s\n\036%s' | fio collect" % (
-            json.dumps(feature, indent=2), json.dumps(feature, indent=2)),
-        shell=True)
-    collection = json.loads(result.decode('utf-8'))
-    assert len(collection['features']) == 2
-    assert collection['features'][0] == feature
+def test_info_bounds():
+    runner = CliRunner()
+    result = runner.invoke(fio.info, ['--bounds', WILDSHP])
+    assert result.exit_code == 0
+    assert len(re.findall(r'\d*\.\d*', result.output)) == 4
diff --git a/tests/test_collection.py b/tests/test_collection.py
index 128bcec..ebd45e0 100644
--- a/tests/test_collection.py
+++ b/tests/test_collection.py
@@ -13,10 +13,14 @@ import fiona
 from fiona.collection import Collection, supported_drivers
 from fiona.errors import FionaValueError, DriverError, SchemaError, CRSError
 
-logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
+
+WILDSHP = 'tests/data/coutwildrnp.shp'
+
+#logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
 TEMPDIR = tempfile.gettempdir()
 
+
 class SupportedDriversTest(unittest.TestCase):
     def test_shapefile(self):
         self.failUnless("ESRI Shapefile" in supported_drivers)
@@ -27,6 +31,7 @@ class SupportedDriversTest(unittest.TestCase):
         self.failUnlessEqual(
             set(supported_drivers["MapInfo File"]), set("raw") )
 
+
 class CollectionArgsTest(unittest.TestCase):
     def test_path(self):
         self.assertRaises(TypeError, Collection, (0))
@@ -65,14 +70,16 @@ class CollectionArgsTest(unittest.TestCase):
     def test_append_geojson(self):
         self.assertRaises(ValueError, Collection, ("foo"), mode='w', driver='ARCGEN')
 
+
 class OpenExceptionTest(unittest.TestCase):
     def test_no_archive(self):
         self.assertRaises(IOError, fiona.open, ("/"), mode='r', vfs="zip:///foo.zip")
 
+
 class ReadingTest(unittest.TestCase):
     
     def setUp(self):
-        self.c = fiona.open("docs/data/test_uk.shp", "r")
+        self.c = fiona.open(WILDSHP, "r")
     
     def tearDown(self):
         self.c.close()
@@ -80,21 +87,21 @@ class ReadingTest(unittest.TestCase):
     def test_open_repr(self):
         self.failUnlessEqual(
             repr(self.c),
-            ("<open Collection 'docs/data/test_uk.shp:test_uk', mode 'r' "
+            ("<open Collection 'tests/data/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_closed_repr(self):
         self.c.close()
         self.failUnlessEqual(
             repr(self.c),
-            ("<closed Collection 'docs/data/test_uk.shp:test_uk', mode 'r' "
+            ("<closed Collection 'tests/data/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_path(self):
-        self.failUnlessEqual(self.c.path, 'docs/data/test_uk.shp')
+        self.failUnlessEqual(self.c.path, WILDSHP)
 
     def test_name(self):
-        self.failUnlessEqual(self.c.name, 'test_uk')
+        self.failUnlessEqual(self.c.name, 'coutwildrnp')
     
     def test_mode(self):
         self.failUnlessEqual(self.c.mode, 'r')
@@ -110,7 +117,7 @@ class ReadingTest(unittest.TestCase):
         self.assertRaises(ValueError, iter, self.c)
 
     def test_len(self):
-        self.failUnlessEqual(len(self.c), 48)
+        self.failUnlessEqual(len(self.c), 67)
     
     def test_closed_len(self):
         # Len is lazy, it's never computed in this case. TODO?
@@ -121,7 +128,7 @@ class ReadingTest(unittest.TestCase):
         # Lazy len is computed in this case and sticks.
         len(self.c)
         self.c.close()
-        self.failUnlessEqual(len(self.c), 48)
+        self.failUnlessEqual(len(self.c), 67)
     
     def test_driver(self):
         self.failUnlessEqual(self.c.driver, "ESRI Shapefile")
@@ -137,8 +144,11 @@ class ReadingTest(unittest.TestCase):
     
     def test_schema(self):
         s = self.c.schema['properties']
-        self.failUnlessEqual(s['CAT'], "float:16")
-        self.failUnlessEqual(s['FIPS_CNTRY'], "str:80")
+        self.failUnlessEqual(s['PERIMETER'], "float:24.15")
+        self.failUnlessEqual(s['NAME'], "str:80")
+        self.failUnlessEqual(s['URL'], "str:101")
+        self.failUnlessEqual(s['STATE_FIPS'], "str:80")
+        self.failUnlessEqual(s['WILDRNP020'], "int:10")
 
     def test_closed_schema(self):
         # Schema is lazy too, never computed in this case. TODO?
@@ -178,38 +188,38 @@ class ReadingTest(unittest.TestCase):
             ['crs', 'driver', 'schema'])
 
     def test_bounds(self):
-        self.failUnlessAlmostEqual(self.c.bounds[0], -8.621389, 6)
-        self.failUnlessAlmostEqual(self.c.bounds[1], 49.911659, 6)
-        self.failUnlessAlmostEqual(self.c.bounds[2], 1.749444, 6)
-        self.failUnlessAlmostEqual(self.c.bounds[3], 60.844444, 6)
+        self.failUnlessAlmostEqual(self.c.bounds[0], -113.564247, 6)
+        self.failUnlessAlmostEqual(self.c.bounds[1], 37.068981, 6)
+        self.failUnlessAlmostEqual(self.c.bounds[2], -104.970871, 6)
+        self.failUnlessAlmostEqual(self.c.bounds[3], 41.996277, 6)
 
     def test_context(self):
-        with fiona.open("docs/data/test_uk.shp", "r") as c:
-            self.failUnlessEqual(c.name, 'test_uk')
-            self.failUnlessEqual(len(c), 48)
+        with fiona.open(WILDSHP, "r") as c:
+            self.failUnlessEqual(c.name, 'coutwildrnp')
+            self.failUnlessEqual(len(c), 67)
         self.failUnlessEqual(c.closed, True)
 
     def test_iter_one(self):
         itr = iter(self.c)
         f = next(itr)
         self.failUnlessEqual(f['id'], "0")
-        self.failUnlessEqual(f['properties']['FIPS_CNTRY'], 'UK')
+        self.failUnlessEqual(f['properties']['STATE'], 'UT')
 
     def test_iter_list(self):
         f = list(self.c)[0]
         self.failUnlessEqual(f['id'], "0")
-        self.failUnlessEqual(f['properties']['FIPS_CNTRY'], 'UK')
+        self.failUnlessEqual(f['properties']['STATE'], 'UT')
 
     def test_re_iter_list(self):
         f = list(self.c)[0] # Run through iterator
         f = list(self.c)[0] # Run through a new, reset iterator
         self.failUnlessEqual(f['id'], "0")
-        self.failUnlessEqual(f['properties']['FIPS_CNTRY'], 'UK')
+        self.failUnlessEqual(f['properties']['STATE'], 'UT')
 
     def test_getitem_one(self):
         f = self.c[0]
         self.failUnlessEqual(f['id'], "0")
-        self.failUnlessEqual(f['properties']['FIPS_CNTRY'], 'UK')
+        self.failUnlessEqual(f['properties']['STATE'], 'UT')
 
     def test_getitem_iter_combo(self):
         i = iter(self.c)
@@ -228,7 +238,7 @@ class ReadingTest(unittest.TestCase):
         i, f = list(self.c.items())[0]
         self.failUnlessEqual(i, 0)
         self.failUnlessEqual(f['id'], "0")
-        self.failUnlessEqual(f['properties']['FIPS_CNTRY'], 'UK')
+        self.failUnlessEqual(f['properties']['STATE'], 'UT')
 
     def test_iter_keys_list(self):
         i = list(self.c.keys())[0]
@@ -240,26 +250,34 @@ class ReadingTest(unittest.TestCase):
 
 
 class FilterReadingTest(unittest.TestCase):
+
     def setUp(self):
-        self.c = fiona.open("docs/data/test_uk.shp", "r")
+        self.c = fiona.open(WILDSHP, "r")
+
     def tearDown(self):
         self.c.close()
+
     def test_filter_1(self):
-        results = list(self.c.filter(bbox=(-15.0, 35.0, 15.0, 65.0)))
-        self.failUnlessEqual(len(results), 48)
+        results = list(self.c.filter(bbox=(-120.0, 30.0, -100.0, 50.0)))
+        self.failUnlessEqual(len(results), 67)
         f = results[0]
         self.failUnlessEqual(f['id'], "0")
-        self.failUnlessEqual(f['properties']['FIPS_CNTRY'], 'UK')
+        self.failUnlessEqual(f['properties']['STATE'], 'UT')
+
     def test_filter_reset(self):
-        results = list(self.c.filter(bbox=(-15.0, 55.0, 15.0, 65.0)))
-        self.failUnlessEqual(len(results), 41)
+        results = list(self.c.filter(bbox=(-112.0, 38.0, -106.0, 40.0)))
+        self.failUnlessEqual(len(results), 26)
         results = list(self.c.filter())
-        self.failUnlessEqual(len(results), 48)
+        self.failUnlessEqual(len(results), 67)
         
     def test_filter_mask(self):
-        mask = {'type': 'Polygon', 'coordinates': (((-2.0, 60.0), (-2.0, 60.0), (0.0, 61.0), (0.0, 60.0), (-2.0, 60.0)),)}
+        mask = {
+            'type': 'Polygon',
+            'coordinates': (
+                ((-112, 38), (-112, 40), (-106, 40), (-106, 38), (-112, 38)),)}
         results = list(self.c.filter(mask=mask))
-        self.failUnlessEqual(len(results), 1)
+        self.failUnlessEqual(len(results), 26)
+
 
 class UnsupportedDriverTest(unittest.TestCase):
     
@@ -271,6 +289,7 @@ class UnsupportedDriverTest(unittest.TestCase):
             DriverError, 
             fiona.open, os.path.join(TEMPDIR, "foo"), "w", "Bogus", schema=schema)
 
+
 class GenericWritingTest(unittest.TestCase):
 
     def setUp(self):
@@ -298,6 +317,7 @@ class GenericWritingTest(unittest.TestCase):
     def test_no_filter(self):
         self.assertRaises(IOError, self.c.filter)
 
+
 class PointWritingTest(unittest.TestCase):
 
     def setUp(self):
@@ -320,7 +340,10 @@ class PointWritingTest(unittest.TestCase):
     def test_cpg(self):
         """Requires GDAL 1.9"""
         self.sink.close()
-        self.failUnless(open(os.path.join(self.tempdir, "point_writing_test.cpg")).readline() == 'UTF-8')
+        self.failUnless(
+            open(
+                os.path.join(self.tempdir, "point_writing_test.cpg")
+                ).readline() == 'UTF-8')
 
     def test_write_one(self):
         self.failUnlessEqual(len(self.sink), 0)
@@ -371,6 +394,7 @@ class PointWritingTest(unittest.TestCase):
         self.assertTrue(self.sink.validate_record(fvalid))
         self.assertFalse(self.sink.validate_record(finvalid))
 
+
 class LineWritingTest(unittest.TestCase):
 
     def setUp(self):
@@ -416,18 +440,19 @@ class LineWritingTest(unittest.TestCase):
         self.failUnlessEqual(len(self.sink), 2)
         self.failUnlessEqual(self.sink.bounds, (0.0, -0.2, 0.0, 0.2))
 
+
 class PointAppendTest(unittest.TestCase):
     # Tests 3D shapefiles too
     def setUp(self):
         self.tempdir = tempfile.mkdtemp()
-        with fiona.open("docs/data/test_uk.shp", "r") as input:
+        with fiona.open(WILDSHP, "r") as input:
             output_schema = input.schema.copy()
             output_schema['geometry'] = '3D Point'
             with fiona.open(
                     os.path.join(self.tempdir, "test_append_point.shp"),
                     "w", crs=None, driver="ESRI Shapefile", schema=output_schema
                     ) as output:
-                for f in input.filter(bbox=(-5.0, 55.0, 0.0, 60.0)):
+                for f in input:
                     f['geometry'] = {
                         'type': 'Point',
                         'coordinates': f['geometry']['coordinates'][0][0] }
@@ -440,12 +465,18 @@ class PointAppendTest(unittest.TestCase):
         with fiona.open(os.path.join(self.tempdir, "test_append_point.shp"), "a") as c:
             self.assertEqual(c.schema['geometry'], '3D Point')
             c.write({'geometry': {'type': 'Point', 'coordinates': (0.0, 45.0)},
-                     'properties': { 'FIPS_CNTRY': 'UK', 
-                                     'AREA': 0.0, 
-                                     'CAT': 1.0, 
-                                     'POP_CNTRY': 0, 
-                                     'CNTRY_NAME': u'Foo'} })
-            self.assertEqual(len(c), 8)
+                     'properties': { 'PERIMETER': 1.0,
+                                     'FEATURE2': None,
+                                     'NAME': 'Foo',
+                                     'FEATURE1': None,
+                                     'URL': 'http://example.com',
+                                     'AGBUR': 'BAR',
+                                     'AREA': 0.0,
+                                     'STATE_FIPS': 1,
+                                     'WILDRNP020': 1,
+                                     'STATE': 'XL' } })
+            self.assertEqual(len(c), 68)
+
 
 class LineAppendTest(unittest.TestCase):
 
@@ -484,6 +515,7 @@ class LineAppendTest(unittest.TestCase):
             self.failUnlessEqual(len(c), 3)
             self.failUnlessEqual(c.bounds, (0.0, -0.2, 0.0, 0.2))
 
+
 class ShapefileFieldWidthTest(unittest.TestCase):
     
     def test_text(self):
@@ -504,6 +536,7 @@ class ShapefileFieldWidthTest(unittest.TestCase):
     def tearDown(self):
         shutil.rmtree(self.tempdir)
 
+
 class CollectionTest(unittest.TestCase):
 
     def test_invalid_mode(self):
@@ -523,6 +556,7 @@ class CollectionTest(unittest.TestCase):
     def test_no_read_directory(self):
         self.assertRaises(ValueError, fiona.open, "/dev/null", "r")
 
+
 class GeoJSONCRSWritingTest(unittest.TestCase):
 
     def setUp(self):
@@ -550,7 +584,9 @@ class GeoJSONCRSWritingTest(unittest.TestCase):
             'GEOGCS["WGS 84' in info.decode('utf-8'),
             info)
 
+
 class DateTimeTest(unittest.TestCase):
+
     def setUp(self):
         self.tempdir = tempfile.mkdtemp()
 
diff --git a/tests/test_drivers.py b/tests/test_drivers.py
index a8621aa..18ef430 100644
--- a/tests/test_drivers.py
+++ b/tests/test_drivers.py
@@ -1,4 +1,3 @@
-
 import logging
 import os.path
 import shutil
@@ -7,6 +6,9 @@ import tempfile
 
 import fiona
 
+
+logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
+
 def test_options(tmpdir=None):
     """Test that setting CPL_DEBUG=ON works"""
     if tmpdir is None:
@@ -21,7 +23,7 @@ def test_options(tmpdir=None):
     logger.addHandler(fh)
 
     with fiona.drivers(CPL_DEBUG=True):
-        c = fiona.open("docs/data/test_uk.shp")
+        c = fiona.open("tests/data/coutwildrnp.shp")
         c.close()
         log = open(logfile).read()
         assert "Option CPL_DEBUG" in log
diff --git a/tests/test_fio_bounds.py b/tests/test_fio_bounds.py
index 45a77a1..328b62e 100644
--- a/tests/test_fio_bounds.py
+++ b/tests/test_fio_bounds.py
@@ -1,13 +1,13 @@
 import json
+import re
 
 import click
 from click.testing import CliRunner
 
 from fiona.fio import bounds
 
-
-input = u'\x1e{"geometry": {"coordinates": [[[100094.81257811641, 6684726.008762141], [98548.69617048775, 6684924.5976624405], [87664.09899970173, 6686905.046363058], [86952.87877302397, 6687103.688267614], [85283.08641112497, 6688045.252446961], [84540.91936600611, 6688936.450241844], [82963.96745943041, 6691364.418923092], [82469.15232285221, 6692405.682380612], [81819.82573305666, 6693843.436658373], [82438.31682390235, 6697660.772804541], [83365.94214068248, 6700140.454427341], [8463 [...]
-
+from .fixtures import (
+    feature_collection, feature_collection_pp, feature_seq, feature_seq_pp_rs)
 
 
 def test_fail():
@@ -16,71 +16,80 @@ def test_fail():
     assert result.exit_code == 1
 
 
-def test_bounds():
+def test_seq():
+    runner = CliRunner()
+    result = runner.invoke(bounds.bounds, [], feature_seq)
+    assert result.exit_code == 0
+    assert result.output.count('[') == result.output.count(']') == 2
+    assert len(re.findall(r'\d*\.\d*', result.output)) == 8
+
+
+def test_seq_rs():
+    runner = CliRunner()
+    result = runner.invoke(bounds.bounds, [], feature_seq_pp_rs)
+    assert result.exit_code == 0
+    assert result.output.count('[') == result.output.count(']') == 2
+    assert len(re.findall(r'\d*\.\d*', result.output)) == 8
+
+
+def test_precision():
     runner = CliRunner()
-    result = runner.invoke(bounds.bounds, [], input)
+    result = runner.invoke(bounds.bounds, ['--precision', 1], feature_seq)
     assert result.exit_code == 0
-    assert len(json.loads(result.output.strip())) == 4
-    assert round(json.loads(result.output.strip())[0], 1) ==  81819.8
+    assert result.output.count('[') == result.output.count(']') == 2
+    assert len(re.findall(r'\d*\.\d{1}\D', result.output)) == 8
 
 
-def test_bounds_precision():
+def test_explode():
     runner = CliRunner()
-    result = runner.invoke(bounds.bounds, ['--precision', 1], input)
+    result = runner.invoke(bounds.bounds, ['--explode'], feature_collection)
     assert result.exit_code == 0
-    assert len(json.loads(result.output.strip())) == 4
-    assert json.loads(result.output.strip())[0] ==  81819.8
+    assert result.output.count('[') == result.output.count(']') == 2
+    assert len(re.findall(r'\d*\.\d*', result.output)) == 8
 
 
-def test_bounds_explode():
+def test_explode_pp():
     runner = CliRunner()
-    result = runner.invoke(bounds.bounds, ['--explode'], input)
+    result = runner.invoke(bounds.bounds, ['--explode'], feature_collection_pp)
     assert result.exit_code == 0
-    assert len(json.loads(result.output.strip())) == 4
-    assert round(json.loads(result.output.strip())[0], 1) ==  81819.8
+    assert result.output.count('[') == result.output.count(']') == 2
+    assert len(re.findall(r'\d*\.\d*', result.output)) == 8
 
 
-def test_bounds_with_id():
+def test_with_id():
     runner = CliRunner()
-    result = runner.invoke(bounds.bounds, ['--with-id'], input)
+    result = runner.invoke(bounds.bounds, ['--with-id'], feature_seq)
     assert result.exit_code == 0
-    obj = json.loads(result.output.strip())
-    assert 'id' in obj
-    assert 'bbox' in obj
-    assert len(obj['bbox']) == 4
-    assert round(obj['bbox'][0], 1) ==  81819.8
+    assert result.output.count('id') == result.output.count('bbox') == 2
 
 
-def test_bounds_explode_with_id():
+def test_explode_with_id():
     runner = CliRunner()
-    result = runner.invoke(bounds.bounds, ['--explode', '--with-id'], input)
+    result = runner.invoke(
+        bounds.bounds, ['--explode', '--with-id'], feature_collection)
     assert result.exit_code == 0
-    obj = json.loads(result.output.strip())
-    assert 'id' in obj
-    assert 'bbox' in obj
-    assert len(obj['bbox']) == 4
-    assert round(obj['bbox'][0], 1) ==  81819.8
+    assert result.output.count('id') == result.output.count('bbox') == 2
 
 
-def test_bounds_with_obj():
+def test_with_obj():
     runner = CliRunner()
-    result = runner.invoke(bounds.bounds, ['--with-obj'], input)
+    result = runner.invoke(bounds.bounds, ['--with-obj'], feature_seq)
     assert result.exit_code == 0
-    obj = json.loads(result.output.strip())
-    assert 'geometry' in obj
-    assert 'id' in obj
-    assert 'bbox' in obj
-    assert len(obj['bbox']) == 4
-    assert round(obj['bbox'][0], 1) ==  81819.8
+    assert result.output.count('geometry') == result.output.count('bbox') == 2
 
 
 def test_bounds_explode_with_obj():
     runner = CliRunner()
-    result = runner.invoke(bounds.bounds, ['--explode', '--with-obj'], input)
+    result = runner.invoke(
+        bounds.bounds, ['--explode', '--with-obj'], feature_collection)
+    assert result.exit_code == 0
+    assert result.output.count('geometry') == result.output.count('bbox') == 2
+
+
+def test_explode_output_rs():
+    runner = CliRunner()
+    result = runner.invoke(bounds.bounds, ['--explode', '--rs'], feature_collection)
     assert result.exit_code == 0
-    obj = json.loads(result.output.strip())
-    assert 'geometry' in obj
-    assert 'id' in obj
-    assert 'bbox' in obj
-    assert len(obj['bbox']) == 4
-    assert round(obj['bbox'][0], 1) ==  81819.8
+    assert result.output.count(u'\u001e') == 2
+    assert result.output.count('[') == result.output.count(']') == 2
+    assert len(re.findall(r'\d*\.\d*', result.output)) == 8
diff --git a/tests/test_fio_cat.py b/tests/test_fio_cat.py
index e865a08..7ba5b4e 100644
--- a/tests/test_fio_cat.py
+++ b/tests/test_fio_cat.py
@@ -5,40 +5,55 @@ from click.testing import CliRunner
 
 from fiona.fio import cat
 
+from .fixtures import (
+    feature_collection, feature_collection_pp, feature_seq, feature_seq_pp_rs)
 
-input = u'\x1e{"geometry": {"coordinates": [[[100094.81257811641, 6684726.008762141], [98548.69617048775, 6684924.5976624405], [87664.09899970173, 6686905.046363058], [86952.87877302397, 6687103.688267614], [85283.08641112497, 6688045.252446961], [84540.91936600611, 6688936.450241844], [82963.96745943041, 6691364.418923092], [82469.15232285221, 6692405.682380612], [81819.82573305666, 6693843.436658373], [82438.31682390235, 6697660.772804541], [83365.94214068248, 6700140.454427341], [8463 [...]
 
-input_collection = u'\x1e{"features": [{"geometry": {"coordinates": [[[100094.81257811641, 6684726.008762141], [98548.69617048775, 6684924.5976624405], [87664.09899970173, 6686905.046363058], [86952.87877302397, 6687103.688267614], [85283.08641112497, 6688045.252446961], [84540.91936600611, 6688936.450241844], [82963.96745943041, 6691364.418923092], [82469.15232285221, 6692405.682380612], [81819.82573305666, 6693843.436658373], [82438.31682390235, 6697660.772804541], [83365.94214068248,  [...]
+WILDSHP = 'tests/data/coutwildrnp.shp'
 
 
-def test_cat():
+def test_one():
+    runner = CliRunner()
+    result = runner.invoke(cat.cat, [WILDSHP])
+    assert result.exit_code == 0
+    assert result.output.count('"Feature"') == 67
+
+
+def test_two():
+    runner = CliRunner()
+    result = runner.invoke(cat.cat, [WILDSHP, WILDSHP])
+    assert result.exit_code == 0
+    assert result.output.count('"Feature"') == 134
+
+
+def test_bbox_no():
     runner = CliRunner()
     result = runner.invoke(
         cat.cat,
-        ['docs/data/test_uk.shp'],
+        [WILDSHP, '--bbox', '0,10,80,20'],
         catch_exceptions=False)
     assert result.exit_code == 0
-    assert result.output.count('"Feature"') == 48
+    assert result.output == ""
 
 
-def test_cat_bbox_no():
+def test_bbox_yes():
     runner = CliRunner()
     result = runner.invoke(
         cat.cat,
-        ['docs/data/test_uk.shp', '--bbox', '-90,10,-80,20'],
+        [WILDSHP, '--bbox', '-109,37,-107,39'],
         catch_exceptions=False)
     assert result.exit_code == 0
-    assert result.output == ""
+    assert result.output.count('"Feature"') == 19
 
 
-def test_cat_bbox_yes():
+def test_bbox_json_yes():
     runner = CliRunner()
     result = runner.invoke(
         cat.cat,
-        ['docs/data/test_uk.shp', '--bbox', '-10,50,0,60'],
+        [WILDSHP, '--bbox', '[-109,37,-107,39]'],
         catch_exceptions=False)
     assert result.exit_code == 0
-    assert result.output.count('"Feature"') == 44
+    assert result.output.count('"Feature"') == 19
 
 
 def test_collect_rs():
@@ -46,10 +61,10 @@ def test_collect_rs():
     result = runner.invoke(
         cat.collect,
         ['--src_crs', 'EPSG:3857'],
-        input,
+        feature_seq_pp_rs,
         catch_exceptions=False)
     assert result.exit_code == 0
-    assert result.output == u'{"features": [{"geometry": {"coordinates": [[[0.8991670000000086, 51.357216], [0.8852780000000007, 51.358329999999995], [0.7874999999999889, 51.369438], [0.7811109999999931, 51.37055199999999], [0.766110999999994, 51.375831999999996], [0.7594439999999931, 51.380828999999984], [0.7452780000000093, 51.39443999999999], [0.7408329999999906, 51.40027599999999], [0.735000000000005, 51.408332999999985], [0.7405559999999894, 51.42971799999999], [0.7488889999999875,  [...]
+    assert result.output.count('"Feature"') == 2
 
 
 def test_collect_no_rs():
@@ -57,10 +72,10 @@ def test_collect_no_rs():
     result = runner.invoke(
         cat.collect,
         ['--src_crs', 'EPSG:3857'],
-        input,
+        feature_seq,
         catch_exceptions=False)
     assert result.exit_code == 0
-    assert result.output == u'{"features": [{"geometry": {"coordinates": [[[0.8991670000000086, 51.357216], [0.8852780000000007, 51.358329999999995], [0.7874999999999889, 51.369438], [0.7811109999999931, 51.37055199999999], [0.766110999999994, 51.375831999999996], [0.7594439999999931, 51.380828999999984], [0.7452780000000093, 51.39443999999999], [0.7408329999999906, 51.40027599999999], [0.735000000000005, 51.408332999999985], [0.7405559999999894, 51.42971799999999], [0.7488889999999875,  [...]
+    assert result.output.count('"Feature"') == 2
 
 
 def test_collect_ld():
@@ -68,7 +83,7 @@ def test_collect_ld():
     result = runner.invoke(
         cat.collect,
         ['--with-ld-context', '--add-ld-context-item', 'foo=bar'],
-        input,
+        feature_seq,
         catch_exceptions=False)
     assert result.exit_code == 0
     assert '"@context": {' in result.output
@@ -77,29 +92,27 @@ def test_collect_ld():
 
 def test_collect_rec_buffered():
     runner = CliRunner()
-    result = runner.invoke(cat.collect, ['--record-buffered'], input)
+    result = runner.invoke(cat.collect, ['--record-buffered'], feature_seq)
     assert result.exit_code == 0
     assert '"FeatureCollection"' in result.output
 
 
 def test_distrib():
     runner = CliRunner()
-    result = runner.invoke(cat.distrib, [], input)
+    result = runner.invoke(cat.distrib, [], feature_collection_pp)
     assert result.exit_code == 0
-    assert json.loads(result.output.strip())['id'] == '0'
-
+    assert result.output.count('"Feature"') == 2
 
 
-def test_distrib():
+def test_distrib_no_rs():
     runner = CliRunner()
-    result = runner.invoke(cat.distrib, [], input_collection)
+    result = runner.invoke(cat.distrib, [], feature_collection)
     assert result.exit_code == 0
-    assert json.loads(result.output.strip())['parent'] == 'collection:0'
-    assert json.loads(result.output.strip())['id'] == '0'
+    assert result.output.count('"Feature"') == 2
 
 
 def test_dump():
     runner = CliRunner()
-    result = runner.invoke(cat.dump, ['docs/data/test_uk.shp'])
+    result = runner.invoke(cat.dump, [WILDSHP])
     assert result.exit_code == 0
     assert '"FeatureCollection"' in result.output
diff --git a/tests/test_fio_load.py b/tests/test_fio_load.py
new file mode 100644
index 0000000..5702576
--- /dev/null
+++ b/tests/test_fio_load.py
@@ -0,0 +1,70 @@
+import json
+import os
+import tempfile
+
+import click
+from click.testing import CliRunner
+
+import fiona
+from fiona.fio import fio
+
+from .fixtures import (
+    feature_collection, feature_collection_pp, feature_seq, feature_seq_pp_rs)
+
+
+def test_err():
+    runner = CliRunner()
+    result = runner.invoke(
+        fio.load, [], '', catch_exceptions=False)
+    assert result.exit_code == 2
+
+
+def test_exception(tmpdir=None):
+    if tmpdir is None:
+        tmpdir = tempfile.mkdtemp()
+        tmpfile = os.path.join(tmpdir, 'test.shp')
+    else:
+        tmpfile = str(tmpdir.join('test.shp'))
+    runner = CliRunner()
+    result = runner.invoke(
+        fio.load, ['-f', 'Shapefile', tmpfile], '42', catch_exceptions=False)
+    assert result.exit_code == 1
+
+
+def test_collection(tmpdir=None):
+    if tmpdir is None:
+        tmpdir = tempfile.mkdtemp()
+        tmpfile = os.path.join(tmpdir, 'test.shp')
+    else:
+        tmpfile = str(tmpdir.join('test.shp'))
+    runner = CliRunner()
+    result = runner.invoke(
+        fio.load, ['-f', 'Shapefile', tmpfile], feature_collection)
+    assert result.exit_code == 0
+    assert len(fiona.open(tmpfile)) == 2
+
+
+def test_seq_rs(tmpdir=None):
+    if tmpdir is None:
+        tmpdir = tempfile.mkdtemp()
+        tmpfile = os.path.join(tmpdir, 'test.shp')
+    else:
+        tmpfile = str(tmpdir.join('test.shp'))
+    runner = CliRunner()
+    result = runner.invoke(
+        fio.load, ['-f', 'Shapefile', tmpfile], feature_seq_pp_rs)
+    assert result.exit_code == 0
+    assert len(fiona.open(tmpfile)) == 2
+
+
+def test_seq_no_rs(tmpdir=None):
+    if tmpdir is None:
+        tmpdir = tempfile.mkdtemp()
+        tmpfile = os.path.join(tmpdir, 'test.shp')
+    else:
+        tmpfile = str(tmpdir.join('test.shp'))
+    runner = CliRunner()
+    result = runner.invoke(
+        fio.load, ['-f', 'Shapefile', '--sequence', tmpfile], feature_seq)
+    assert result.exit_code == 0
+    assert len(fiona.open(tmpfile)) == 2
diff --git a/tests/test_geojson.py b/tests/test_geojson.py
index 59454e4..79b41c8 100644
--- a/tests/test_geojson.py
+++ b/tests/test_geojson.py
@@ -16,13 +16,13 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 class ReadingTest(unittest.TestCase):
     
     def setUp(self):
-        self.c = fiona.open('docs/data/test_uk.json', 'r')
+        self.c = fiona.open('tests/data/coutwildrnp.json', 'r')
     
     def tearDown(self):
         self.c.close()
 
     def test_json(self):
-        self.assertEquals(len(self.c), 48)
+        self.assertEquals(len(self.c), 67)
 
 class WritingTest(unittest.TestCase):
 
diff --git a/tests/test_geopackage.py b/tests/test_geopackage.py
index d990d34..3572183 100644
--- a/tests/test_geopackage.py
+++ b/tests/test_geopackage.py
@@ -26,13 +26,13 @@ class ReadingTest(unittest.TestCase):
     def tearDown(self):
         pass
 
-    @pytest.mark.skipif(not os.path.exists('docs/data/test_uk.gpkg'),
+    @pytest.mark.skipif(not os.path.exists('tests/data/coutwildrnp.gpkg'),
                         reason="Requires geopackage fixture")
     def test_gpkg(self):
         if get_gdal_version_num() < calc_gdal_version_num(1, 11, 0):
-            self.assertRaises(DriverError, fiona.open, 'docs/data/test_uk.gpkg', 'r', driver="GPKG")
+            self.assertRaises(DriverError, fiona.open, 'tests/data/coutwildrnp.gpkg', 'r', driver="GPKG")
         else:
-            with fiona.open('docs/data/test_uk.gpkg', 'r', driver="GPKG") as c:
+            with fiona.open('tests/data/coutwildrnp.gpkg', 'r', driver="GPKG") as c:
                 self.assertEquals(len(c), 48)
 
 
@@ -44,7 +44,7 @@ class WritingTest(unittest.TestCase):
     def tearDown(self):
         shutil.rmtree(self.tempdir)
 
-    @pytest.mark.skipif(not os.path.exists('docs/data/test_uk.gpkg'),
+    @pytest.mark.skipif(not os.path.exists('tests/data/coutwildrnp.gpkg'),
                         reason="Requires geopackage fixture")
     def test_gpkg(self):
         schema = {'geometry': 'Point',
diff --git a/tests/test_layer.py b/tests/test_layer.py
index f5970f0..3e2ff15 100644
--- a/tests/test_layer.py
+++ b/tests/test_layer.py
@@ -12,13 +12,13 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 from .test_collection import ReadingTest
 
 def test_index_selection():
-    with fiona.open('docs/data/test_uk.shp', 'r', layer=0) as c:
-        assert len(c) == 48
+    with fiona.open('tests/data/coutwildrnp.shp', 'r', layer=0) as c:
+        assert len(c) == 67
 
 class FileReadingTest(ReadingTest):
     
     def setUp(self):
-        self.c = fiona.open('docs/data/test_uk.shp', 'r', layer='test_uk')
+        self.c = fiona.open('tests/data/coutwildrnp.shp', 'r', layer='coutwildrnp')
     
     def tearDown(self):
         self.c.close()
@@ -26,23 +26,23 @@ class FileReadingTest(ReadingTest):
     def test_open_repr(self):
         self.failUnlessEqual(
             repr(self.c),
-            ("<open Collection 'docs/data/test_uk.shp:test_uk', mode 'r' "
+            ("<open Collection 'tests/data/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_closed_repr(self):
         self.c.close()
         self.failUnlessEqual(
             repr(self.c),
-            ("<closed Collection 'docs/data/test_uk.shp:test_uk', mode 'r' "
+            ("<closed Collection 'tests/data/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_name(self):
-        self.failUnlessEqual(self.c.name, 'test_uk')
+        self.failUnlessEqual(self.c.name, 'coutwildrnp')
 
 class DirReadingTest(ReadingTest):
     
     def setUp(self):
-        self.c = fiona.open("docs/data", "r", layer="test_uk")
+        self.c = fiona.open("tests/data", "r", layer="coutwildrnp")
     
     def tearDown(self):
         self.c.close()
@@ -50,26 +50,26 @@ class DirReadingTest(ReadingTest):
     def test_open_repr(self):
         self.failUnlessEqual(
             repr(self.c),
-            ("<open Collection 'docs/data:test_uk', mode 'r' "
+            ("<open Collection 'tests/data:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_closed_repr(self):
         self.c.close()
         self.failUnlessEqual(
             repr(self.c),
-            ("<closed Collection 'docs/data:test_uk', mode 'r' "
+            ("<closed Collection 'tests/data:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_name(self):
-        self.failUnlessEqual(self.c.name, 'test_uk')
+        self.failUnlessEqual(self.c.name, 'coutwildrnp')
 
     def test_path(self):
-        self.failUnlessEqual(self.c.path, "docs/data")
+        self.failUnlessEqual(self.c.path, "tests/data")
 
 class InvalidLayerTest(unittest.TestCase):
 
     def test_invalid(self):
-        self.assertRaises(ValueError, fiona.open, ("docs/data/test_uk.shp"), layer="foo")
+        self.assertRaises(ValueError, fiona.open, ("tests/data/coutwildrnp.shp"), layer="foo")
 
     def test_write_numeric_layer(self):
         self.assertRaises(ValueError, fiona.open,
diff --git a/tests/test_listing.py b/tests/test_listing.py
index f8f0b52..9e4d2c8 100644
--- a/tests/test_listing.py
+++ b/tests/test_listing.py
@@ -11,22 +11,22 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
 def test_single_file_private():
     with fiona.drivers():
-        assert fiona.ogrext._listlayers('docs/data/test_uk.shp') == ['test_uk']
+        assert fiona.ogrext._listlayers('tests/data/coutwildrnp.shp') == ['coutwildrnp']
 
 def test_single_file():
-    assert fiona.listlayers('docs/data/test_uk.shp') == ['test_uk']
+    assert fiona.listlayers('tests/data/coutwildrnp.shp') == ['coutwildrnp']
 
 def test_directory():
-    assert fiona.listlayers('docs/data') == ['test_uk']
+    assert fiona.listlayers('tests/data') == ['coutwildrnp']
 
 def test_directory_trailing_slash():
-    assert fiona.listlayers('docs/data/') == ['test_uk']
+    assert fiona.listlayers('tests/data/') == ['coutwildrnp']
 
 def test_zip_path():
-    assert fiona.listlayers('zip://docs/data/test_uk.zip') == ['test_uk']
+    assert fiona.listlayers('zip://tests/data/coutwildrnp.zip') == ['coutwildrnp']
 
 def test_zip_path_arch():
-    assert fiona.listlayers('/test_uk.shp', vfs='zip://docs/data/test_uk.zip') == ['test_uk']
+    assert fiona.listlayers('/coutwildrnp.shp', vfs='zip://tests/data/coutwildrnp.zip') == ['coutwildrnp']
 
 class ListLayersArgsTest(unittest.TestCase):
     def test_path(self):
diff --git a/tests/test_multiconxn.py b/tests/test_multiconxn.py
index dc0034b..2fed3e5 100644
--- a/tests/test_multiconxn.py
+++ b/tests/test_multiconxn.py
@@ -15,19 +15,19 @@ class ReadAccess(unittest.TestCase):
     # in a single file.
     
     def setUp(self):
-        self.c = fiona.open("docs/data/test_uk.shp", "r", layer="test_uk")
+        self.c = fiona.open("tests/data/coutwildrnp.shp", "r", layer="coutwildrnp")
     
     def tearDown(self):
         self.c.close()
 
     def test_meta(self):
-        with fiona.open("docs/data/test_uk.shp", "r", layer="test_uk") as c2:
+        with fiona.open("tests/data/coutwildrnp.shp", "r", layer="coutwildrnp") as c2:
             self.assertEqual(len(self.c), len(c2))
             self.assertEqual(sorted(self.c.schema.items()), sorted(c2.schema.items()))
 
     def test_meta(self):
         f1 = next(self.c)
-        with fiona.open("docs/data/test_uk.shp", "r", layer="test_uk") as c2:
+        with fiona.open("tests/data/coutwildrnp.shp", "r", layer="coutwildrnp") as c2:
             f2 = next(c2)
             self.assertEqual(f1, f2)
 
@@ -121,4 +121,3 @@ class LayerCreation(unittest.TestCase):
         f2 = next(c2)
         del f2['id']
         self.assertEqual(self.f, f2)
-
diff --git a/tests/test_non_counting_layer.py b/tests/test_non_counting_layer.py
new file mode 100644
index 0000000..f33f4db
--- /dev/null
+++ b/tests/test_non_counting_layer.py
@@ -0,0 +1,35 @@
+import unittest
+
+import fiona
+
+GPX_FILE = 'tests/data/test_gpx.gpx'
+
+class NonCountingLayerTest(unittest.TestCase):
+    def setUp(self):
+        self.c = fiona.open(GPX_FILE, "r", layer="track_points")
+    
+    def tearDown(self):
+        self.c.close()
+
+    def test_len_fail(self):
+        with self.assertRaises(TypeError):
+            len(self.c)
+
+    def test_list(self):
+        features = list(self.c)
+        self.assertEquals(len(features), 19)
+
+    def test_getitem(self):
+        feature = self.c[2]
+
+    def test_fail_getitem_negative_index(self):
+        with self.assertRaises(IndexError):
+            self.c[-1]
+
+    def test_slice(self):
+        features = self.c[2:5]
+        self.assertEquals(len(features), 3)
+
+    def test_fail_slice_negative_index(self):
+        with self.assertRaises(IndexError):
+            self.c[2:-4]
diff --git a/tests/test_read_drivers.py b/tests/test_read_drivers.py
new file mode 100644
index 0000000..fd42a92
--- /dev/null
+++ b/tests/test_read_drivers.py
@@ -0,0 +1,26 @@
+import logging
+import sys
+
+import pytest
+
+import fiona
+from fiona.errors import FionaValueError
+
+
+logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
+
+def test_read_fail():
+    with pytest.raises(FionaValueError):
+        fiona.open('tests/data/coutwildrnp.shp', driver='GeoJSON')
+    with pytest.raises(FionaValueError):
+        fiona.open('tests/data/coutwildrnp.shp', enabled_drivers=['GeoJSON'])
+
+
+def test_read():
+    with fiona.open(
+            'tests/data/coutwildrnp.shp', driver='ESRI Shapefile') as src:
+        assert src.driver == 'ESRI Shapefile'
+    with fiona.open(
+            'tests/data/coutwildrnp.shp',
+            enabled_drivers=['GeoJSON', 'ESRI Shapefile']) as src:
+        assert src.driver == 'ESRI Shapefile'
diff --git a/tests/test_revolvingdoor.py b/tests/test_revolvingdoor.py
index 5da4edb..ba402e0 100644
--- a/tests/test_revolvingdoor.py
+++ b/tests/test_revolvingdoor.py
@@ -23,7 +23,7 @@ class RevolvingDoorTest(unittest.TestCase):
 
     def test_write_revolving_door(self):
 
-        with fiona.open('docs/data/test_uk.shp') as src:
+        with fiona.open('tests/data/coutwildrnp.shp') as src:
             meta = src.meta
             features = list(src)
 
@@ -34,4 +34,3 @@ class RevolvingDoorTest(unittest.TestCase):
 
         with fiona.open(shpname) as src:
             pass
-
diff --git a/tests/test_slice.py b/tests/test_slice.py
index 6e4d62a..57e0394 100644
--- a/tests/test_slice.py
+++ b/tests/test_slice.py
@@ -6,19 +6,19 @@ import fiona
 logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
 def test_collection_get():
-    with fiona.open('docs/data/test_uk.shp') as src:
+    with fiona.open('tests/data/coutwildrnp.shp') as src:
         result = src[5]
         assert result['id'] == '5'
 
 def test_collection_slice():
-    with fiona.open('docs/data/test_uk.shp') as src:
+    with fiona.open('tests/data/coutwildrnp.shp') as src:
         results = src[:5]
         assert isinstance(results, list)
         assert len(results) == 5
         assert results[4]['id'] == '4'
 
 def test_collection_iterator_slice():
-    with fiona.open('docs/data/test_uk.shp') as src:
+    with fiona.open('tests/data/coutwildrnp.shp') as src:
         results = list(src.items(5))
         assert len(results) == 5
         k, v = results[4]
@@ -26,14 +26,14 @@ def test_collection_iterator_slice():
         assert v['id'] == '4'
 
 def test_collection_iterator_next():
-    with fiona.open('docs/data/test_uk.shp') as src:
+    with fiona.open('tests/data/coutwildrnp.shp') as src:
         k, v = next(src.items(5, None))
         assert k == 5
         assert v['id'] == '5'
 
 def test_collection_iterator_items_slice():
 
-    with fiona.open('docs/data/test_uk.shp') as src:
+    with fiona.open('tests/data/coutwildrnp.shp') as src:
         l = len(src)
 
         items = list(src.items(0, 5))
@@ -70,6 +70,6 @@ def test_collection_iterator_items_slice():
         assert len(items) == (l - 5 + 1)
 
 def test_collection_iterator_keys_next():
-    with fiona.open('docs/data/test_uk.shp') as src:
+    with fiona.open('tests/data/coutwildrnp.shp') as src:
         k = next(src.keys(5, None))
         assert k == 5
diff --git a/tests/test_unicode.py b/tests/test_unicode.py
index 2266124..5e94876 100644
--- a/tests/test_unicode.py
+++ b/tests/test_unicode.py
@@ -18,30 +18,29 @@ class UnicodePathTest(unittest.TestCase):
     def setUp(self):
         tempdir = tempfile.mkdtemp()
         self.dir = os.path.join(tempdir, 'français')
-        shutil.copytree('docs/data/', self.dir)
+        shutil.copytree('tests/data/', self.dir)
 
     def tearDown(self):
         shutil.rmtree(os.path.dirname(self.dir))
 
     def test_unicode_path(self):
-        path = self.dir + '/test_uk.shp'
+        path = self.dir + '/coutwildrnp.shp'
         if sys.version_info < (3,):
             path = path.decode('utf-8')
         with fiona.open(path) as c:
-            assert len(c) == 48
+            assert len(c) == 67
 
     def test_unicode_path_layer(self):
         path = self.dir
-        layer = 'test_uk'
+        layer = 'coutwildrnp'
         if sys.version_info < (3,):
             path = path.decode('utf-8')
             layer = layer.decode('utf-8')
         with fiona.open(path, layer=layer) as c:
-            assert len(c) == 48
+            assert len(c) == 67
 
     def test_utf8_path(self):
-        path = self.dir + '/test_uk.shp'
+        path = self.dir + '/coutwildrnp.shp'
         if sys.version_info < (3,):
             with fiona.open(path) as c:
-                assert len(c) == 48
-
+                assert len(c) == 67
diff --git a/tests/test_vfs.py b/tests/test_vfs.py
index c73f06c..0687aa1 100644
--- a/tests/test_vfs.py
+++ b/tests/test_vfs.py
@@ -20,16 +20,16 @@ class VsiReadingTest(ReadingTest):
     # from the test runner at run time.
 
     def test_filter_vsi(self):
-        results = list(self.c.filter(bbox=(-15.0, 35.0, 15.0, 65.0)))
-        self.failUnlessEqual(len(results), 48)
+        results = list(self.c.filter(bbox=(-114.0, 35.0, -104, 45.0)))
+        self.failUnlessEqual(len(results), 67)
         f = results[0]
         self.failUnlessEqual(f['id'], "0")
-        self.failUnlessEqual(f['properties']['FIPS_CNTRY'], 'UK')
+        self.failUnlessEqual(f['properties']['STATE'], 'UT')
 
 class ZipReadingTest(VsiReadingTest):
     
     def setUp(self):
-        self.c = fiona.open("zip://docs/data/test_uk.zip", "r")
+        self.c = fiona.open("zip://tests/data/coutwildrnp.zip", "r")
     
     def tearDown(self):
         self.c.close()
@@ -37,23 +37,23 @@ class ZipReadingTest(VsiReadingTest):
     def test_open_repr(self):
         self.failUnlessEqual(
             repr(self.c),
-            ("<open Collection '/vsizip/docs/data/test_uk.zip:test_uk', mode 'r' "
+            ("<open Collection '/vsizip/tests/data/coutwildrnp.zip:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_closed_repr(self):
         self.c.close()
         self.failUnlessEqual(
             repr(self.c),
-            ("<closed Collection '/vsizip/docs/data/test_uk.zip:test_uk', mode 'r' "
+            ("<closed Collection '/vsizip/tests/data/coutwildrnp.zip:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_path(self):
-        self.failUnlessEqual(self.c.path, '/vsizip/docs/data/test_uk.zip')
+        self.failUnlessEqual(self.c.path, '/vsizip/tests/data/coutwildrnp.zip')
 
 class ZipArchiveReadingTest(VsiReadingTest):
     
     def setUp(self):
-        self.c = fiona.open("/test_uk.shp", "r", vfs="zip://docs/data/test_uk.zip")
+        self.c = fiona.open("/coutwildrnp.shp", "r", vfs="zip://tests/data/coutwildrnp.zip")
     
     def tearDown(self):
         self.c.close()
@@ -61,23 +61,23 @@ class ZipArchiveReadingTest(VsiReadingTest):
     def test_open_repr(self):
         self.failUnlessEqual(
             repr(self.c),
-            ("<open Collection '/vsizip/docs/data/test_uk.zip/test_uk.shp:test_uk', mode 'r' "
+            ("<open Collection '/vsizip/tests/data/coutwildrnp.zip/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_closed_repr(self):
         self.c.close()
         self.failUnlessEqual(
             repr(self.c),
-            ("<closed Collection '/vsizip/docs/data/test_uk.zip/test_uk.shp:test_uk', mode 'r' "
+            ("<closed Collection '/vsizip/tests/data/coutwildrnp.zip/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_path(self):
-        self.failUnlessEqual(self.c.path, '/vsizip/docs/data/test_uk.zip/test_uk.shp')
+        self.failUnlessEqual(self.c.path, '/vsizip/tests/data/coutwildrnp.zip/coutwildrnp.shp')
 
 class TarArchiveReadingTest(VsiReadingTest):
     
     def setUp(self):
-        self.c = fiona.open("/testing/test_uk.shp", "r", vfs="tar://docs/data/test_uk.tar")
+        self.c = fiona.open("/testing/coutwildrnp.shp", "r", vfs="tar://tests/data/coutwildrnp.tar")
     
     def tearDown(self):
         self.c.close()
@@ -85,16 +85,16 @@ class TarArchiveReadingTest(VsiReadingTest):
     def test_open_repr(self):
         self.failUnlessEqual(
             repr(self.c),
-            ("<open Collection '/vsitar/docs/data/test_uk.tar/testing/test_uk.shp:test_uk', mode 'r' "
+            ("<open Collection '/vsitar/tests/data/coutwildrnp.tar/testing/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_closed_repr(self):
         self.c.close()
         self.failUnlessEqual(
             repr(self.c),
-            ("<closed Collection '/vsitar/docs/data/test_uk.tar/testing/test_uk.shp:test_uk', mode 'r' "
+            ("<closed Collection '/vsitar/tests/data/coutwildrnp.tar/testing/coutwildrnp.shp:coutwildrnp', mode 'r' "
             "at %s>" % hex(id(self.c))))
 
     def test_path(self):
-        self.failUnlessEqual(self.c.path, '/vsitar/docs/data/test_uk.tar/testing/test_uk.shp')
+        self.failUnlessEqual(self.c.path, '/vsitar/tests/data/coutwildrnp.tar/testing/coutwildrnp.shp')
 

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