Repository: rasterio/rasterio

Issue:
Change sharing default to False in rasterio.open
The unexpected behavior noted in #1504 makes me think we should reverse the default for sharing that was set in #1260. Not sharing dataset handles == fewer surprises. 


Discussion:

Resolving patch:
diff --git a/rasterio/__init__.py b/rasterio/__init__.py
--- a/rasterio/__init__.py
+++ b/rasterio/__init__.py
@@ -56,7 +56,7 @@ def emit(self, record):
 
 @ensure_env_with_credentials
 def open(fp, mode='r', driver=None, width=None, height=None, count=None,
-         crs=None, transform=None, dtype=None, nodata=None, sharing=True,
+         crs=None, transform=None, dtype=None, nodata=None, sharing=False,
          **kwargs):
     """Open a dataset for reading or writing.
 
@@ -110,9 +110,9 @@ def open(fp, mode='r', driver=None, width=None, height=None, count=None,
     sharing : bool; optional
         To reduce overhead and prevent programs from running out of file
         descriptors, rasterio maintains a pool of shared low level
-        dataset handles. When `True` (the default), this function will
-        use a shared handle if one is available. Multithreaded programs
-        must avoid sharing and should set *sharing* to `False`.
+        dataset handles. When `True` this function will use a shared
+        handle if one is available. Multithreaded programs must avoid
+        sharing and should set *sharing* to `False`.
     kwargs : optional
         These are passed to format drivers as directives for creating or
         interpreting datasets. For example: in 'w' or 'w+' modes
diff --git a/rasterio/features.py b/rasterio/features.py
--- a/rasterio/features.py
+++ b/rasterio/features.py
@@ -283,7 +283,7 @@ def format_cast_error(param, dtype):
 
             else:
                 valid_shapes.append((geom, value))
-        
+
         else:
             # invalid or empty geometries are skipped and raise a warning instead
             warnings.warn('Invalid or empty shape at index {} will not be rasterized.'.format(index))


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -6,11 +6,11 @@
 import os
 import shutil
 import sys
+import uuid
 import zipfile
 
 import affine
 from click.testing import CliRunner
-import py
 import pytest
 import numpy as np
 
@@ -579,6 +579,13 @@ def path_zip_file(data_dir):
     return path
 
 
+@pytest.fixture(autouse=True)
+def set_mem_name(request, monkeypatch):
+    def youyoueyedeefour():
+        return "{}-{}".format(request.node.name, uuid.uuid4())
+    monkeypatch.setattr(rasterio._io, "uuid4", youyoueyedeefour)
+
+
 class MockGeoInterface(object):
     """Tiny wrapper for GeoJSON to present an object with __geo_interface__ for testing"""
     def __init__(self, geojson):
diff --git a/tests/test_features.py b/tests/test_features.py
--- a/tests/test_features.py
+++ b/tests/test_features.py
@@ -1130,9 +1130,14 @@ def test_sieve_band(pixelated_image, pixelated_image_file):
         )
 
 
-def test_sieve_internal_driver_manager(basic_image, pixelated_image):
+def test_sieve_internal_driver_manager(capfd, basic_image, pixelated_image):
     """Sieve should work without explicitly calling driver manager."""
-    assert np.array_equal(
-        basic_image,
-        sieve(pixelated_image, basic_image.sum())
-    )
+    with rasterio.Env() as env:
+        assert np.array_equal(
+            basic_image,
+            sieve(pixelated_image, basic_image.sum())
+        )
+
+        env._dump_open_datasets()
+        captured = capfd.readouterr()
+        assert not captured.err
diff --git a/tests/test_open_options.py b/tests/test_open_options.py
--- a/tests/test_open_options.py
+++ b/tests/test_open_options.py
@@ -8,20 +8,6 @@
 from .conftest import requires_only_gdal1, requires_gdal2, requires_gdal22
 
 
-@requires_only_gdal1
-def test_driver_option_not_implemented():
-    """Driver selection is not supported by GDAL 1.x"""
-    with pytest.raises(rasterio.errors.GDALOptionNotImplementedError):
-        rasterio.open('tests/data/RGB.byte.tif', driver='BMP')
-
-
-@requires_only_gdal1
-def test_open_options_not_implemented():
-    """Open options are not supported by GDAL 1.x"""
-    with pytest.raises(rasterio.errors.GDALOptionNotImplementedError):
-        rasterio.open('tests/data/RGB.byte.tif', NUM_THREADS=42)
-
-
 @requires_gdal2
 def test_fail_with_missing_driver():
     """Fail to open a GeoTIFF without the GTiff driver"""
diff --git a/tests/test_open_sharing.py b/tests/test_open_sharing.py
--- a/tests/test_open_sharing.py
+++ b/tests/test_open_sharing.py
@@ -11,7 +11,7 @@ def test_sharing_on(capfd, path_rgb_byte_tif):
     with rasterio.Env() as env:
 
         # Opens a new file.
-        with rasterio.open(path_rgb_byte_tif, sharing=False) as srcx:
+        with rasterio.open(path_rgb_byte_tif) as srcx:
             env._dump_open_datasets()
             captured = capfd.readouterr()
             assert "1 N GTiff" in captured.err
@@ -37,7 +37,7 @@ def test_sharing_off(capfd, path_rgb_byte_tif):
             assert "1 N GTiff" in captured.err
             assert "1 S GTiff" not in captured.err
 
-            # Does not open a new file.
+            # Opens a new file.
             with rasterio.open(path_rgb_byte_tif, sharing=False) as srcy:
                 env._dump_open_datasets()
                 captured = capfd.readouterr()
diff --git a/tests/test_warpedvrt.py b/tests/test_warpedvrt.py
--- a/tests/test_warpedvrt.py
+++ b/tests/test_warpedvrt.py
@@ -127,13 +127,9 @@ def test_warped_vrt_msk_nodata(path_rgb_msk_byte_tif, caplog):
         assert vrt.count == 3
         assert vrt.mask_flag_enums == ([MaskFlags.nodata],) * 3
 
-        caplog.set_level(logging.DEBUG)
-        with rasterio.Env(CPL_DEBUG=True):
-            masks = vrt.read_masks()
-            assert masks[0, 0, 0] == 0
-            assert masks[0].mean() > 0
-
-        assert "RGB2.byte.tif.msk" in caplog.text
+        masks = vrt.read_masks()
+        assert masks[0, 0, 0] == 0
+        assert masks[0].mean() > 0
 
 
 def test_warped_vrt_source(path_rgb_byte_tif):
@@ -412,7 +408,7 @@ def test_warpedvrt_float32_override(data):
             assert src.dtypes == vrt.dtypes == ("float32",)
 
 
-def test_warpedvrt_float32_overridei_nodata(data):
+def test_warpedvrt_float32_override_nodata(data):
     """Override GDAL defaults for working data type"""
     float32file = str(data.join("float32.tif"))
     with rasterio.open(float32file, "r+") as dst:
@@ -433,3 +429,24 @@ def test_warpedvrt_issue1744(data):
     with rasterio.open(float32file) as src:
         with WarpedVRT(src, src_crs="EPSG:4326") as vrt:
             assert src.dtypes == vrt.dtypes == ("float32",)
+
+
+@requires_gdal2
+def test_open_datasets(capfd, path_rgb_byte_tif):
+    """Number of open datasets is expected"""
+    with rasterio.Env() as env:
+
+        with rasterio.open(path_rgb_byte_tif) as src:
+            env._dump_open_datasets()
+            captured = capfd.readouterr()
+            assert "1 N GTiff" in captured.err
+            assert "1 S GTiff" not in captured.err
+
+            with WarpedVRT(src) as vrt:
+                env._dump_open_datasets()
+                captured = capfd.readouterr()
+                assert "2 N GTiff" in captured.err
+
+        env._dump_open_datasets()
+        captured = capfd.readouterr()
+        assert not captured.err