We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
In-memory GDAL datasets, sqlite style
GDAL has a concept of in-memory datasets that you create by passing in a filename like `/vsimem/example.tif`. There's a per-process in-memory filesystem at `/vsimem` and a TIFF file in it at `/vsimem/example.tif`. For Rasterio's purposes it could be better to follow the example of sqlite and simply pass, say, `:memory:`. Rasterio could generate a UUID and an appropriate VSIMEM filename to pass to GDAL.

I'm thinking that this could be used to simply the existing code in rio-mbtiles

``` python
    with rasterio.open('/vsimem/tileimg', 'w', **kwds) as tmp:
        reproject(rasterio.band(src, src.indexes),
                  rasterio.band(tmp, tmp.indexes))

    data = bytearray(virtual_file_to_buffer('/vsimem/tileimg'))

    # Workaround for https://bugs.python.org/issue23349.
    if sys.version_info[0] == 2 and sys.version_info[2] < 10:
        data[:] = data[-1:] + data[:-1]

    return tile, data
```

down to 

``` python
    with rasterio.open(':memory:', 'w', **kwds) as tmp:
        reproject(rasterio.band(src, src.indexes),
                  rasterio.band(tmp, tmp.indexes))
        data = tmp.to_bytes()

    return tile, data
```

Benefits:
- More appropriate abstraction for Rasterio, where `open()` is supposed to be the sole access to datasets.
- Prevents mixups on the vsimem filesystem that could be hard to recover from and debug.
- We can workaround the Python bug for all users within `to_bytes()`.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `rasterio/io.py`
Content:
```
1 """Classes capable of reading and writing datasets
2 
3 Instances of these classes are called dataset objects.
4 """
5 
6 import math
7 import warnings
8 
9 from rasterio._base import (
10     get_dataset_driver, driver_can_create, driver_can_create_copy)
11 from rasterio._io import (
12     DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase)
13 from rasterio import enums, windows
14 from rasterio.transform import guard_transform, xy, rowcol
15 
16 
17 class TransformMethodsMixin(object):
18     """Mixin providing methods for calculations related
19     to transforming between rows and columns of the raster
20     array and the coordinates.
21 
22     These methods are wrappers for the functionality in
23     `rasterio.transform` module.
24 
25     A subclass with this mixin MUST provide a `transform`
26     property.
27     """
28 
29     def xy(self, row, col, offset="center"):
30         """Returns the coordinates ``(x, y)`` of a pixel at `row` and `col`.
31         The pixel's center is returned by default, but a corner can be returned
32         by setting `offset` to one of `ul, ur, ll, lr`.
33 
34         Parameters
35         ----------
36         row : int
37             Pixel row.
38         col : int
39             Pixel column.
40         offset : str, optional
41             Determines if the returned coordinates are for the center of the
42             pixel or for a corner.
43 
44         Returns
45         -------
46         tuple
47             ``(x, y)``
48         """
49         return xy(self.transform, row, col, offset=offset)
50 
51     def ul(self, row, col):
52         """Returns the coordinates (x, y) of the upper left corner of a
53         pixel at `row` and `col` in the units of the dataset's
54         coordinate reference system.
55 
56         Deprecated; Use `xy(row, col, offset='ul')` instead.
57         """
58         warnings.warn("ul method is deprecated. Use xy(row, col, offset='ul')",
59                       DeprecationWarning)
60         return xy(self.transform, row, col, offset='ul')
61 
62     def index(self, x, y, op=math.floor, precision=6):
63         """
64         Returns the (row, col) index of the pixel containing (x, y) given a
65         coordinate reference system.
66 
67         Use an epsilon, magnitude determined by the precision parameter
68         and sign determined by the op function:
69             positive for floor, negative for ceil.
70 
71         Parameters
72         ----------
73         x : float
74             x value in coordinate reference system
75         y : float
76             y value in coordinate reference system
77         op : function, optional (default: math.floor)
78             Function to convert fractional pixels to whole numbers (floor,
79             ceiling, round)
80         precision : int, optional (default: 6)
81             Decimal places of precision in indexing, as in `round()`.
82 
83         Returns
84         -------
85         tuple
86             (row index, col index)
87         """
88         return rowcol(self.transform, x, y, op=op, precision=precision)
89 
90 
91 class WindowMethodsMixin(object):
92     """Mixin providing methods for window-related calculations.
93     These methods are wrappers for the functionality in
94     `rasterio.windows` module.
95 
96     A subclass with this mixin MUST provide the following
97     properties: `transform`, `height` and `width`
98     """
99 
100     def window(self, left, bottom, right, top, boundless=False):
101         """Get the window corresponding to the bounding coordinates.
102 
103         Parameters
104         ----------
105         left : float
106             Left (west) bounding coordinate
107         bottom : float
108             Bottom (south) bounding coordinate
109         right : float
110             Right (east) bounding coordinate
111         top : float
112             Top (north) bounding coordinate
113         boundless: boolean, optional
114             If boundless is False, window is limited
115             to extent of this dataset.
116 
117         Returns
118         -------
119         window: tuple
120             ((row_start, row_stop), (col_start, col_stop))
121             corresponding to the bounding coordinates
122 
123         """
124 
125         transform = guard_transform(self.transform)
126         return windows.from_bounds(
127             left, bottom, right, top, transform=transform,
128             height=self.height, width=self.width, boundless=boundless)
129 
130     def window_transform(self, window):
131         """Get the affine transform for a dataset window.
132 
133         Parameters
134         ----------
135         window: tuple
136             Dataset window tuple
137 
138         Returns
139         -------
140         transform: Affine
141             The affine transform matrix for the given window
142         """
143 
144         transform = guard_transform(self.transform)
145         return windows.transform(window, transform)
146 
147     def window_bounds(self, window):
148         """Get the bounds of a window
149 
150         Parameters
151         ----------
152         window: tuple
153             Dataset window tuple
154 
155         Returns
156         -------
157         bounds : tuple
158             x_min, y_min, x_max, y_max for the given window
159         """
160 
161         transform = guard_transform(self.transform)
162         return windows.bounds(window, transform)
163 
164 
165 class DatasetReader(DatasetReaderBase, WindowMethodsMixin,
166                     TransformMethodsMixin):
167     """An unbuffered data and metadata reader"""
168 
169     def __repr__(self):
170         return "<{} DatasetReader name='{}' mode='{}'>".format(
171             self.closed and 'closed' or 'open', self.name, self.mode)
172 
173 class DatasetWriter(DatasetWriterBase, WindowMethodsMixin,
174                     TransformMethodsMixin):
175     """An unbuffered data and metadata writer. Its methods write data
176     directly to disk.
177     """
178 
179     def __repr__(self):
180         return "<{} DatasetWriter name='{}' mode='{}'>".format(
181             self.closed and 'closed' or 'open', self.name, self.mode)
182 
183 
184 class BufferedDatasetWriter(BufferedDatasetWriterBase, WindowMethodsMixin,
185                             TransformMethodsMixin):
186     """Maintains data and metadata in a buffer, writing to disk or
187     network only when `close()` is called.
188 
189     This allows incremental updates to datasets using formats that don't
190     otherwise support updates, such as JPEG.
191     """
192 
193     def __repr__(self):
194         return "<{} BufferedDatasetWriter name='{}' mode='{}'>".format(
195             self.closed and 'closed' or 'open', self.name, self.mode)
196 
197 
198 def get_writer_for_driver(driver):
199     """Return the writer class appropriate for the specified driver."""
200     cls = None
201     if driver_can_create(driver):
202         cls = DatasetWriter
203     elif driver_can_create_copy(driver):  # pragma: no branch
204         cls = BufferedDatasetWriter
205     return cls
206 
207 
208 def get_writer_for_path(path):
209     """Return the writer class appropriate for the existing dataset."""
210     driver = get_dataset_driver(path)
211     return get_writer_for_driver(driver)
212
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/rasterio/io.py b/rasterio/io.py
--- a/rasterio/io.py
+++ b/rasterio/io.py
@@ -3,17 +3,23 @@
 Instances of these classes are called dataset objects.
 """
 
+import logging
 import math
+import uuid
 import warnings
 
 from rasterio._base import (
     get_dataset_driver, driver_can_create, driver_can_create_copy)
 from rasterio._io import (
-    DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase)
+    DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase,
+    MemoryFileBase)
 from rasterio import enums, windows
 from rasterio.transform import guard_transform, xy, rowcol
 
 
+log = logging.getLogger(__name__)
+
+
 class TransformMethodsMixin(object):
     """Mixin providing methods for calculations related
     to transforming between rows and columns of the raster
@@ -170,6 +176,7 @@
         return "<{} DatasetReader name='{}' mode='{}'>".format(
             self.closed and 'closed' or 'open', self.name, self.mode)
 
+
 class DatasetWriter(DatasetWriterBase, WindowMethodsMixin,
                     TransformMethodsMixin):
     """An unbuffered data and metadata writer. Its methods write data
@@ -195,6 +202,68 @@
             self.closed and 'closed' or 'open', self.name, self.mode)
 
 
+class MemoryFile(MemoryFileBase):
+    """A BytesIO-like object, backed by an in-memory file.
+
+    This allows formatted files to be read and written without I/O.
+
+    A MemoryFile created with initial bytes becomes immutable. A
+    MemoryFile created without initial bytes may be written to using
+    either file-like or dataset interfaces.
+
+    Examples
+    --------
+
+    A GeoTIFF can be loaded in memory and accessed using the GeoTIFF
+    format driver
+
+    >>> with open('tests/data/RGB.byte.tif', 'rb') as f, \
+    ...         MemoryFile(f.read()) as memfile:
+    ...     with memfile.open() as src:
+    ...         pprint.pprint(src.profile)
+    ...
+    {'count': 3,
+     'crs': CRS({'init': 'epsg:32618'}),
+     'driver': 'GTiff',
+     'dtype': 'uint8',
+     'height': 718,
+     'interleave': 'pixel',
+     'nodata': 0.0,
+     'tiled': False,
+     'transform': Affine(300.0379266750948, 0.0, 101985.0,
+           0.0, -300.041782729805, 2826915.0),
+     'width': 791}
+
+    """
+
+    def open(self, driver=None, width=None, height=None,
+             count=None, crs=None, transform=None, dtype=None, nodata=None,
+             **kwargs):
+        """Open the file and return a Rasterio dataset object.
+
+        If data has already been written, the file is opened in 'r+'
+        mode. Otherwise, the file is opened in 'w' mode.
+        """
+        if self.closed:
+            raise IOError("I/O operation on closed file.")
+        if self.exists():
+            s = get_writer_for_path(self.name)(self.name, 'r+')
+        else:
+            s = get_writer_for_driver(driver)(self.name, 'w', driver=driver,
+                                              width=width, height=height,
+                                              count=count, crs=crs,
+                                              transform=transform, dtype=dtype,
+                                              nodata=nodata, **kwargs)
+        s.start()
+        return s
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args, **kwargs):
+        self.close()
+
+
 def get_writer_for_driver(driver):
     """Return the writer class appropriate for the specified driver."""
     cls = None

{"golden_diff": "diff --git a/rasterio/io.py b/rasterio/io.py\n--- a/rasterio/io.py\n+++ b/rasterio/io.py\n@@ -3,17 +3,23 @@\n Instances of these classes are called dataset objects.\n \"\"\"\n \n+import logging\n import math\n+import uuid\n import warnings\n \n from rasterio._base import (\n     get_dataset_driver, driver_can_create, driver_can_create_copy)\n from rasterio._io import (\n-    DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase)\n+    DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase,\n+    MemoryFileBase)\n from rasterio import enums, windows\n from rasterio.transform import guard_transform, xy, rowcol\n \n \n+log = logging.getLogger(__name__)\n+\n+\n class TransformMethodsMixin(object):\n     \"\"\"Mixin providing methods for calculations related\n     to transforming between rows and columns of the raster\n@@ -170,6 +176,7 @@\n         return \"<{} DatasetReader name='{}' mode='{}'>\".format(\n             self.closed and 'closed' or 'open', self.name, self.mode)\n \n+\n class DatasetWriter(DatasetWriterBase, WindowMethodsMixin,\n                     TransformMethodsMixin):\n     \"\"\"An unbuffered data and metadata writer. Its methods write data\n@@ -195,6 +202,68 @@\n             self.closed and 'closed' or 'open', self.name, self.mode)\n \n \n+class MemoryFile(MemoryFileBase):\n+    \"\"\"A BytesIO-like object, backed by an in-memory file.\n+\n+    This allows formatted files to be read and written without I/O.\n+\n+    A MemoryFile created with initial bytes becomes immutable. A\n+    MemoryFile created without initial bytes may be written to using\n+    either file-like or dataset interfaces.\n+\n+    Examples\n+    --------\n+\n+    A GeoTIFF can be loaded in memory and accessed using the GeoTIFF\n+    format driver\n+\n+    >>> with open('tests/data/RGB.byte.tif', 'rb') as f, \\\n+    ...         MemoryFile(f.read()) as memfile:\n+    ...     with memfile.open() as src:\n+    ...         pprint.pprint(src.profile)\n+    ...\n+    {'count': 3,\n+     'crs': CRS({'init': 'epsg:32618'}),\n+     'driver': 'GTiff',\n+     'dtype': 'uint8',\n+     'height': 718,\n+     'interleave': 'pixel',\n+     'nodata': 0.0,\n+     'tiled': False,\n+     'transform': Affine(300.0379266750948, 0.0, 101985.0,\n+           0.0, -300.041782729805, 2826915.0),\n+     'width': 791}\n+\n+    \"\"\"\n+\n+    def open(self, driver=None, width=None, height=None,\n+             count=None, crs=None, transform=None, dtype=None, nodata=None,\n+             **kwargs):\n+        \"\"\"Open the file and return a Rasterio dataset object.\n+\n+        If data has already been written, the file is opened in 'r+'\n+        mode. Otherwise, the file is opened in 'w' mode.\n+        \"\"\"\n+        if self.closed:\n+            raise IOError(\"I/O operation on closed file.\")\n+        if self.exists():\n+            s = get_writer_for_path(self.name)(self.name, 'r+')\n+        else:\n+            s = get_writer_for_driver(driver)(self.name, 'w', driver=driver,\n+                                              width=width, height=height,\n+                                              count=count, crs=crs,\n+                                              transform=transform, dtype=dtype,\n+                                              nodata=nodata, **kwargs)\n+        s.start()\n+        return s\n+\n+    def __enter__(self):\n+        return self\n+\n+    def __exit__(self, *args, **kwargs):\n+        self.close()\n+\n+\n def get_writer_for_driver(driver):\n     \"\"\"Return the writer class appropriate for the specified driver.\"\"\"\n     cls = None\n", "issue": "In-memory GDAL datasets, sqlite style\nGDAL has a concept of in-memory datasets that you create by passing in a filename like `/vsimem/example.tif`. There's a per-process in-memory filesystem at `/vsimem` and a TIFF file in it at `/vsimem/example.tif`. For Rasterio's purposes it could be better to follow the example of sqlite and simply pass, say, `:memory:`. Rasterio could generate a UUID and an appropriate VSIMEM filename to pass to GDAL.\n\nI'm thinking that this could be used to simply the existing code in rio-mbtiles\n\n``` python\n    with rasterio.open('/vsimem/tileimg', 'w', **kwds) as tmp:\n        reproject(rasterio.band(src, src.indexes),\n                  rasterio.band(tmp, tmp.indexes))\n\n    data = bytearray(virtual_file_to_buffer('/vsimem/tileimg'))\n\n    # Workaround for https://bugs.python.org/issue23349.\n    if sys.version_info[0] == 2 and sys.version_info[2] < 10:\n        data[:] = data[-1:] + data[:-1]\n\n    return tile, data\n```\n\ndown to \n\n``` python\n    with rasterio.open(':memory:', 'w', **kwds) as tmp:\n        reproject(rasterio.band(src, src.indexes),\n                  rasterio.band(tmp, tmp.indexes))\n        data = tmp.to_bytes()\n\n    return tile, data\n```\n\nBenefits:\n- More appropriate abstraction for Rasterio, where `open()` is supposed to be the sole access to datasets.\n- Prevents mixups on the vsimem filesystem that could be hard to recover from and debug.\n- We can workaround the Python bug for all users within `to_bytes()`.\n\n", "before_files": [{"content": "\"\"\"Classes capable of reading and writing datasets\n\nInstances of these classes are called dataset objects.\n\"\"\"\n\nimport math\nimport warnings\n\nfrom rasterio._base import (\n    get_dataset_driver, driver_can_create, driver_can_create_copy)\nfrom rasterio._io import (\n    DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase)\nfrom rasterio import enums, windows\nfrom rasterio.transform import guard_transform, xy, rowcol\n\n\nclass TransformMethodsMixin(object):\n    \"\"\"Mixin providing methods for calculations related\n    to transforming between rows and columns of the raster\n    array and the coordinates.\n\n    These methods are wrappers for the functionality in\n    `rasterio.transform` module.\n\n    A subclass with this mixin MUST provide a `transform`\n    property.\n    \"\"\"\n\n    def xy(self, row, col, offset=\"center\"):\n        \"\"\"Returns the coordinates ``(x, y)`` of a pixel at `row` and `col`.\n        The pixel's center is returned by default, but a corner can be returned\n        by setting `offset` to one of `ul, ur, ll, lr`.\n\n        Parameters\n        ----------\n        row : int\n            Pixel row.\n        col : int\n            Pixel column.\n        offset : str, optional\n            Determines if the returned coordinates are for the center of the\n            pixel or for a corner.\n\n        Returns\n        -------\n        tuple\n            ``(x, y)``\n        \"\"\"\n        return xy(self.transform, row, col, offset=offset)\n\n    def ul(self, row, col):\n        \"\"\"Returns the coordinates (x, y) of the upper left corner of a\n        pixel at `row` and `col` in the units of the dataset's\n        coordinate reference system.\n\n        Deprecated; Use `xy(row, col, offset='ul')` instead.\n        \"\"\"\n        warnings.warn(\"ul method is deprecated. Use xy(row, col, offset='ul')\",\n                      DeprecationWarning)\n        return xy(self.transform, row, col, offset='ul')\n\n    def index(self, x, y, op=math.floor, precision=6):\n        \"\"\"\n        Returns the (row, col) index of the pixel containing (x, y) given a\n        coordinate reference system.\n\n        Use an epsilon, magnitude determined by the precision parameter\n        and sign determined by the op function:\n            positive for floor, negative for ceil.\n\n        Parameters\n        ----------\n        x : float\n            x value in coordinate reference system\n        y : float\n            y value in coordinate reference system\n        op : function, optional (default: math.floor)\n            Function to convert fractional pixels to whole numbers (floor,\n            ceiling, round)\n        precision : int, optional (default: 6)\n            Decimal places of precision in indexing, as in `round()`.\n\n        Returns\n        -------\n        tuple\n            (row index, col index)\n        \"\"\"\n        return rowcol(self.transform, x, y, op=op, precision=precision)\n\n\nclass WindowMethodsMixin(object):\n    \"\"\"Mixin providing methods for window-related calculations.\n    These methods are wrappers for the functionality in\n    `rasterio.windows` module.\n\n    A subclass with this mixin MUST provide the following\n    properties: `transform`, `height` and `width`\n    \"\"\"\n\n    def window(self, left, bottom, right, top, boundless=False):\n        \"\"\"Get the window corresponding to the bounding coordinates.\n\n        Parameters\n        ----------\n        left : float\n            Left (west) bounding coordinate\n        bottom : float\n            Bottom (south) bounding coordinate\n        right : float\n            Right (east) bounding coordinate\n        top : float\n            Top (north) bounding coordinate\n        boundless: boolean, optional\n            If boundless is False, window is limited\n            to extent of this dataset.\n\n        Returns\n        -------\n        window: tuple\n            ((row_start, row_stop), (col_start, col_stop))\n            corresponding to the bounding coordinates\n\n        \"\"\"\n\n        transform = guard_transform(self.transform)\n        return windows.from_bounds(\n            left, bottom, right, top, transform=transform,\n            height=self.height, width=self.width, boundless=boundless)\n\n    def window_transform(self, window):\n        \"\"\"Get the affine transform for a dataset window.\n\n        Parameters\n        ----------\n        window: tuple\n            Dataset window tuple\n\n        Returns\n        -------\n        transform: Affine\n            The affine transform matrix for the given window\n        \"\"\"\n\n        transform = guard_transform(self.transform)\n        return windows.transform(window, transform)\n\n    def window_bounds(self, window):\n        \"\"\"Get the bounds of a window\n\n        Parameters\n        ----------\n        window: tuple\n            Dataset window tuple\n\n        Returns\n        -------\n        bounds : tuple\n            x_min, y_min, x_max, y_max for the given window\n        \"\"\"\n\n        transform = guard_transform(self.transform)\n        return windows.bounds(window, transform)\n\n\nclass DatasetReader(DatasetReaderBase, WindowMethodsMixin,\n                    TransformMethodsMixin):\n    \"\"\"An unbuffered data and metadata reader\"\"\"\n\n    def __repr__(self):\n        return \"<{} DatasetReader name='{}' mode='{}'>\".format(\n            self.closed and 'closed' or 'open', self.name, self.mode)\n\nclass DatasetWriter(DatasetWriterBase, WindowMethodsMixin,\n                    TransformMethodsMixin):\n    \"\"\"An unbuffered data and metadata writer. Its methods write data\n    directly to disk.\n    \"\"\"\n\n    def __repr__(self):\n        return \"<{} DatasetWriter name='{}' mode='{}'>\".format(\n            self.closed and 'closed' or 'open', self.name, self.mode)\n\n\nclass BufferedDatasetWriter(BufferedDatasetWriterBase, WindowMethodsMixin,\n                            TransformMethodsMixin):\n    \"\"\"Maintains data and metadata in a buffer, writing to disk or\n    network only when `close()` is called.\n\n    This allows incremental updates to datasets using formats that don't\n    otherwise support updates, such as JPEG.\n    \"\"\"\n\n    def __repr__(self):\n        return \"<{} BufferedDatasetWriter name='{}' mode='{}'>\".format(\n            self.closed and 'closed' or 'open', self.name, self.mode)\n\n\ndef get_writer_for_driver(driver):\n    \"\"\"Return the writer class appropriate for the specified driver.\"\"\"\n    cls = None\n    if driver_can_create(driver):\n        cls = DatasetWriter\n    elif driver_can_create_copy(driver):  # pragma: no branch\n        cls = BufferedDatasetWriter\n    return cls\n\n\ndef get_writer_for_path(path):\n    \"\"\"Return the writer class appropriate for the existing dataset.\"\"\"\n    driver = get_dataset_driver(path)\n    return get_writer_for_driver(driver)\n", "path": "rasterio/io.py"}], "after_files": [{"content": "\"\"\"Classes capable of reading and writing datasets\n\nInstances of these classes are called dataset objects.\n\"\"\"\n\nimport logging\nimport math\nimport uuid\nimport warnings\n\nfrom rasterio._base import (\n    get_dataset_driver, driver_can_create, driver_can_create_copy)\nfrom rasterio._io import (\n    DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase,\n    MemoryFileBase)\nfrom rasterio import enums, windows\nfrom rasterio.transform import guard_transform, xy, rowcol\n\n\nlog = logging.getLogger(__name__)\n\n\nclass TransformMethodsMixin(object):\n    \"\"\"Mixin providing methods for calculations related\n    to transforming between rows and columns of the raster\n    array and the coordinates.\n\n    These methods are wrappers for the functionality in\n    `rasterio.transform` module.\n\n    A subclass with this mixin MUST provide a `transform`\n    property.\n    \"\"\"\n\n    def xy(self, row, col, offset=\"center\"):\n        \"\"\"Returns the coordinates ``(x, y)`` of a pixel at `row` and `col`.\n        The pixel's center is returned by default, but a corner can be returned\n        by setting `offset` to one of `ul, ur, ll, lr`.\n\n        Parameters\n        ----------\n        row : int\n            Pixel row.\n        col : int\n            Pixel column.\n        offset : str, optional\n            Determines if the returned coordinates are for the center of the\n            pixel or for a corner.\n\n        Returns\n        -------\n        tuple\n            ``(x, y)``\n        \"\"\"\n        return xy(self.transform, row, col, offset=offset)\n\n    def ul(self, row, col):\n        \"\"\"Returns the coordinates (x, y) of the upper left corner of a\n        pixel at `row` and `col` in the units of the dataset's\n        coordinate reference system.\n\n        Deprecated; Use `xy(row, col, offset='ul')` instead.\n        \"\"\"\n        warnings.warn(\"ul method is deprecated. Use xy(row, col, offset='ul')\",\n                      DeprecationWarning)\n        return xy(self.transform, row, col, offset='ul')\n\n    def index(self, x, y, op=math.floor, precision=6):\n        \"\"\"\n        Returns the (row, col) index of the pixel containing (x, y) given a\n        coordinate reference system.\n\n        Use an epsilon, magnitude determined by the precision parameter\n        and sign determined by the op function:\n            positive for floor, negative for ceil.\n\n        Parameters\n        ----------\n        x : float\n            x value in coordinate reference system\n        y : float\n            y value in coordinate reference system\n        op : function, optional (default: math.floor)\n            Function to convert fractional pixels to whole numbers (floor,\n            ceiling, round)\n        precision : int, optional (default: 6)\n            Decimal places of precision in indexing, as in `round()`.\n\n        Returns\n        -------\n        tuple\n            (row index, col index)\n        \"\"\"\n        return rowcol(self.transform, x, y, op=op, precision=precision)\n\n\nclass WindowMethodsMixin(object):\n    \"\"\"Mixin providing methods for window-related calculations.\n    These methods are wrappers for the functionality in\n    `rasterio.windows` module.\n\n    A subclass with this mixin MUST provide the following\n    properties: `transform`, `height` and `width`\n    \"\"\"\n\n    def window(self, left, bottom, right, top, boundless=False):\n        \"\"\"Get the window corresponding to the bounding coordinates.\n\n        Parameters\n        ----------\n        left : float\n            Left (west) bounding coordinate\n        bottom : float\n            Bottom (south) bounding coordinate\n        right : float\n            Right (east) bounding coordinate\n        top : float\n            Top (north) bounding coordinate\n        boundless: boolean, optional\n            If boundless is False, window is limited\n            to extent of this dataset.\n\n        Returns\n        -------\n        window: tuple\n            ((row_start, row_stop), (col_start, col_stop))\n            corresponding to the bounding coordinates\n\n        \"\"\"\n\n        transform = guard_transform(self.transform)\n        return windows.from_bounds(\n            left, bottom, right, top, transform=transform,\n            height=self.height, width=self.width, boundless=boundless)\n\n    def window_transform(self, window):\n        \"\"\"Get the affine transform for a dataset window.\n\n        Parameters\n        ----------\n        window: tuple\n            Dataset window tuple\n\n        Returns\n        -------\n        transform: Affine\n            The affine transform matrix for the given window\n        \"\"\"\n\n        transform = guard_transform(self.transform)\n        return windows.transform(window, transform)\n\n    def window_bounds(self, window):\n        \"\"\"Get the bounds of a window\n\n        Parameters\n        ----------\n        window: tuple\n            Dataset window tuple\n\n        Returns\n        -------\n        bounds : tuple\n            x_min, y_min, x_max, y_max for the given window\n        \"\"\"\n\n        transform = guard_transform(self.transform)\n        return windows.bounds(window, transform)\n\n\nclass DatasetReader(DatasetReaderBase, WindowMethodsMixin,\n                    TransformMethodsMixin):\n    \"\"\"An unbuffered data and metadata reader\"\"\"\n\n    def __repr__(self):\n        return \"<{} DatasetReader name='{}' mode='{}'>\".format(\n            self.closed and 'closed' or 'open', self.name, self.mode)\n\n\nclass DatasetWriter(DatasetWriterBase, WindowMethodsMixin,\n                    TransformMethodsMixin):\n    \"\"\"An unbuffered data and metadata writer. Its methods write data\n    directly to disk.\n    \"\"\"\n\n    def __repr__(self):\n        return \"<{} DatasetWriter name='{}' mode='{}'>\".format(\n            self.closed and 'closed' or 'open', self.name, self.mode)\n\n\nclass BufferedDatasetWriter(BufferedDatasetWriterBase, WindowMethodsMixin,\n                            TransformMethodsMixin):\n    \"\"\"Maintains data and metadata in a buffer, writing to disk or\n    network only when `close()` is called.\n\n    This allows incremental updates to datasets using formats that don't\n    otherwise support updates, such as JPEG.\n    \"\"\"\n\n    def __repr__(self):\n        return \"<{} BufferedDatasetWriter name='{}' mode='{}'>\".format(\n            self.closed and 'closed' or 'open', self.name, self.mode)\n\n\nclass MemoryFile(MemoryFileBase):\n    \"\"\"A BytesIO-like object, backed by an in-memory file.\n\n    This allows formatted files to be read and written without I/O.\n\n    A MemoryFile created with initial bytes becomes immutable. A\n    MemoryFile created without initial bytes may be written to using\n    either file-like or dataset interfaces.\n\n    Examples\n    --------\n\n    A GeoTIFF can be loaded in memory and accessed using the GeoTIFF\n    format driver\n\n    >>> with open('tests/data/RGB.byte.tif', 'rb') as f, \\\n    ...         MemoryFile(f.read()) as memfile:\n    ...     with memfile.open() as src:\n    ...         pprint.pprint(src.profile)\n    ...\n    {'count': 3,\n     'crs': CRS({'init': 'epsg:32618'}),\n     'driver': 'GTiff',\n     'dtype': 'uint8',\n     'height': 718,\n     'interleave': 'pixel',\n     'nodata': 0.0,\n     'tiled': False,\n     'transform': Affine(300.0379266750948, 0.0, 101985.0,\n           0.0, -300.041782729805, 2826915.0),\n     'width': 791}\n\n    \"\"\"\n\n    def open(self, driver=None, width=None, height=None,\n             count=None, crs=None, transform=None, dtype=None, nodata=None,\n             **kwargs):\n        \"\"\"Open the file and return a Rasterio dataset object.\n\n        If data has already been written, the file is opened in 'r+'\n        mode. Otherwise, the file is opened in 'w' mode.\n        \"\"\"\n        if self.closed:\n            raise IOError(\"I/O operation on closed file.\")\n        if self.exists():\n            s = get_writer_for_path(self.name)(self.name, 'r+')\n        else:\n            s = get_writer_for_driver(driver)(self.name, 'w', driver=driver,\n                                              width=width, height=height,\n                                              count=count, crs=crs,\n                                              transform=transform, dtype=dtype,\n                                              nodata=nodata, **kwargs)\n        s.start()\n        return s\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, *args, **kwargs):\n        self.close()\n\n\ndef get_writer_for_driver(driver):\n    \"\"\"Return the writer class appropriate for the specified driver.\"\"\"\n    cls = None\n    if driver_can_create(driver):\n        cls = DatasetWriter\n    elif driver_can_create_copy(driver):  # pragma: no branch\n        cls = BufferedDatasetWriter\n    return cls\n\n\ndef get_writer_for_path(path):\n    \"\"\"Return the writer class appropriate for the existing dataset.\"\"\"\n    driver = get_dataset_driver(path)\n    return get_writer_for_driver(driver)\n", "path": "rasterio/io.py"}]}