prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Should rio clip fill nodata at borders?
  Hello lovely people :hugs:,
  
  I'm using `rio clip` to quickly cut out z10 tiles for raster image. The raster image is not divisible by the z10 tiles, so I expect the border tiles to contain nodata. But more importantly I expect all z10 tiles I cut out to be of the same dimension. This is not the case with rio clip right now.
  
  Here is an example where I first convert my raster image to WGS84 and then cut it into z10 tiles where the file name is the z10 quad key id.
  
  ```
  rio warp in.tif wgs84.tif --dst-crs EPSG:4326
  rio bounds wgs84.tif | mercantile tiles 10 > z10.txt
   
  while read tile; do
    rio clip wgs84.tif $(mercantile quadkey "$tile").tif --bounds "$(mercantile shapes --extents "$tile")"
  done < z10.txt
  ```
  
  This results in
  - many raster images of pixel size 2857x1744
  - some raster images (at the borders) with smaller dimensions; the bounds are not filled with nodata
  
  Should rio clip use boundless windows and fill with nodata, to respect the user's bounds?
  
  (rio 1.1.3, tested in ubuntu 18.04 docker container with python 3.6)
  
  --- 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/rio/clip.py`
  Content:
  ```
  1 """File translation command"""
  2 
  3 import logging
  4 
  5 import click
  6 from cligj import format_opt
  7 
  8 from .helpers import resolve_inout
  9 from . import options
  10 import rasterio
  11 from rasterio.coords import disjoint_bounds
  12 from rasterio.crs import CRS
  13 from rasterio.windows import Window
  14 
  15 
  16 logger = logging.getLogger(__name__)
  17 
  18 
  19 # Geographic (default), projected, or Mercator switch.
  20 projection_geographic_opt = click.option(
  21     '--geographic',
  22     'projection',
  23     flag_value='geographic',
  24     help="Bounds in geographic coordinates.")
  25 
  26 projection_projected_opt = click.option(
  27     '--projected',
  28     'projection',
  29     flag_value='projected',
  30     default=True,
  31     help="Bounds in input's own projected coordinates (the default).")
  32 
  33 
  34 # Clip command
  35 @click.command(short_help='Clip a raster to given bounds.')
  36 @click.argument(
  37     'files',
  38     nargs=-1,
  39     type=click.Path(),
  40     required=True,
  41     metavar="INPUT OUTPUT")
  42 @options.output_opt
  43 @options.bounds_opt
  44 @click.option(
  45     '--like',
  46     type=click.Path(exists=True),
  47     help='Raster dataset to use as a template for bounds')
  48 @format_opt
  49 @projection_geographic_opt
  50 @projection_projected_opt
  51 @options.overwrite_opt
  52 @options.creation_options
  53 @click.pass_context
  54 def clip(ctx, files, output, bounds, like, driver, projection,
  55          overwrite, creation_options):
  56     """Clips a raster using projected or geographic bounds.
  57 
  58     \b
  59       $ rio clip input.tif output.tif --bounds xmin ymin xmax ymax
  60       $ rio clip input.tif output.tif --like template.tif
  61 
  62     The values of --bounds are presumed to be from the coordinate
  63     reference system of the input dataset unless the --geographic option
  64     is used, in which case the values may be longitude and latitude
  65     bounds. Either JSON, for example "[west, south, east, north]", or
  66     plain text "west south east north" representations of a bounding box
  67     are acceptable.
  68 
  69     If using --like, bounds will automatically be transformed to match the
  70     coordinate reference system of the input.
  71 
  72     It can also be combined to read bounds of a feature dataset using Fiona:
  73 
  74     \b
  75       $ rio clip input.tif output.tif --bounds $(fio info features.shp --bounds)
  76 
  77     """
  78     from rasterio.warp import transform_bounds
  79 
  80     with ctx.obj['env']:
  81 
  82         output, files = resolve_inout(files=files, output=output, overwrite=overwrite)
  83         input = files[0]
  84 
  85         with rasterio.open(input) as src:
  86             if bounds:
  87                 if projection == 'geographic':
  88                     bounds = transform_bounds(CRS.from_epsg(4326), src.crs, *bounds)
  89                 if disjoint_bounds(bounds, src.bounds):
  90                     raise click.BadParameter('must overlap the extent of '
  91                                              'the input raster',
  92                                              param='--bounds',
  93                                              param_hint='--bounds')
  94             elif like:
  95                 with rasterio.open(like) as template_ds:
  96                     bounds = template_ds.bounds
  97                     if template_ds.crs != src.crs:
  98                         bounds = transform_bounds(template_ds.crs, src.crs,
  99                                                   *bounds)
  100 
  101                     if disjoint_bounds(bounds, src.bounds):
  102                         raise click.BadParameter('must overlap the extent of '
  103                                                  'the input raster',
  104                                                  param='--like',
  105                                                  param_hint='--like')
  106 
  107             else:
  108                 raise click.UsageError('--bounds or --like required')
  109 
  110             bounds_window = src.window(*bounds)
  111             bounds_window = bounds_window.intersection(
  112                 Window(0, 0, src.width, src.height))
  113 
  114             # Get the window with integer height
  115             # and width that contains the bounds window.
  116             out_window = bounds_window.round_lengths(op='ceil')
  117 
  118             height = int(out_window.height)
  119             width = int(out_window.width)
  120 
  121             out_kwargs = src.profile
  122             out_kwargs.update({
  123                 'driver': driver,
  124                 'height': height,
  125                 'width': width,
  126                 'transform': src.window_transform(out_window)})
  127             out_kwargs.update(**creation_options)
  128 
  129             if 'blockxsize' in out_kwargs and out_kwargs['blockxsize'] > width:
  130                 del out_kwargs['blockxsize']
  131                 logger.warning("Blockxsize removed from creation options to accomodate small output width")
  132             if 'blockysize' in out_kwargs and out_kwargs['blockysize'] > height:
  133                 del out_kwargs['blockysize']
  134                 logger.warning("Blockysize removed from creation options to accomodate small output height")
  135 
  136             with rasterio.open(output, 'w', **out_kwargs) as out:
  137                 out.write(src.read(window=out_window,
  138                                    out_shape=(src.count, height, width)))
  139
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/rasterio/rio/clip.py b/rasterio/rio/clip.py
  --- a/rasterio/rio/clip.py
  +++ b/rasterio/rio/clip.py
  @@ -50,9 +50,24 @@
   @projection_projected_opt
   @options.overwrite_opt
   @options.creation_options
  +@click.option(
  +    "--with-complement/--without-complement",
  +    default=False,
  +    help="Include the relative complement of the raster in the given bounds (giving a larger result), else return results only from the intersection of the raster and the bounds (the default).",
  +)
   @click.pass_context
  -def clip(ctx, files, output, bounds, like, driver, projection,
  -         overwrite, creation_options):
  +def clip(
  +    ctx,
  +    files,
  +    output,
  +    bounds,
  +    like,
  +    driver,
  +    projection,
  +    overwrite,
  +    creation_options,
  +    with_complement,
  +):
       """Clips a raster using projected or geographic bounds.
   
       \b
  @@ -108,8 +123,11 @@
                   raise click.UsageError('--bounds or --like required')
   
               bounds_window = src.window(*bounds)
  -            bounds_window = bounds_window.intersection(
  -                Window(0, 0, src.width, src.height))
  +
  +            if not with_complement:
  +                bounds_window = bounds_window.intersection(
  +                    Window(0, 0, src.width, src.height)
  +                )
   
               # Get the window with integer height
               # and width that contains the bounds window.
  @@ -133,6 +151,11 @@
                   del out_kwargs['blockysize']
                   logger.warning("Blockysize removed from creation options to accomodate small output height")
   
  -            with rasterio.open(output, 'w', **out_kwargs) as out:
  -                out.write(src.read(window=out_window,
  -                                   out_shape=(src.count, height, width)))
  +            with rasterio.open(output, "w", **out_kwargs) as out:
  +                out.write(
  +                    src.read(
  +                        window=out_window,
  +                        out_shape=(src.count, height, width),
  +                        boundless=True,
  +                    )
  +                )
  
verification_info: {"golden_diff": "diff --git a/rasterio/rio/clip.py b/rasterio/rio/clip.py\n--- a/rasterio/rio/clip.py\n+++ b/rasterio/rio/clip.py\n@@ -50,9 +50,24 @@\n @projection_projected_opt\n @options.overwrite_opt\n @options.creation_options\n+@click.option(\n+    \"--with-complement/--without-complement\",\n+    default=False,\n+    help=\"Include the relative complement of the raster in the given bounds (giving a larger result), else return results only from the intersection of the raster and the bounds (the default).\",\n+)\n @click.pass_context\n-def clip(ctx, files, output, bounds, like, driver, projection,\n-         overwrite, creation_options):\n+def clip(\n+    ctx,\n+    files,\n+    output,\n+    bounds,\n+    like,\n+    driver,\n+    projection,\n+    overwrite,\n+    creation_options,\n+    with_complement,\n+):\n     \"\"\"Clips a raster using projected or geographic bounds.\n \n     \\b\n@@ -108,8 +123,11 @@\n                 raise click.UsageError('--bounds or --like required')\n \n             bounds_window = src.window(*bounds)\n-            bounds_window = bounds_window.intersection(\n-                Window(0, 0, src.width, src.height))\n+\n+            if not with_complement:\n+                bounds_window = bounds_window.intersection(\n+                    Window(0, 0, src.width, src.height)\n+                )\n \n             # Get the window with integer height\n             # and width that contains the bounds window.\n@@ -133,6 +151,11 @@\n                 del out_kwargs['blockysize']\n                 logger.warning(\"Blockysize removed from creation options to accomodate small output height\")\n \n-            with rasterio.open(output, 'w', **out_kwargs) as out:\n-                out.write(src.read(window=out_window,\n-                                   out_shape=(src.count, height, width)))\n+            with rasterio.open(output, \"w\", **out_kwargs) as out:\n+                out.write(\n+                    src.read(\n+                        window=out_window,\n+                        out_shape=(src.count, height, width),\n+                        boundless=True,\n+                    )\n+                )\n", "issue": "Should rio clip fill nodata at borders?\nHello lovely people :hugs:,\r\n\r\nI'm using `rio clip` to quickly cut out z10 tiles for raster image. The raster image is not divisible by the z10 tiles, so I expect the border tiles to contain nodata. But more importantly I expect all z10 tiles I cut out to be of the same dimension. This is not the case with rio clip right now.\r\n\r\nHere is an example where I first convert my raster image to WGS84 and then cut it into z10 tiles where the file name is the z10 quad key id.\r\n\r\n```\r\nrio warp in.tif wgs84.tif --dst-crs EPSG:4326\r\nrio bounds wgs84.tif | mercantile tiles 10 > z10.txt\r\n \r\nwhile read tile; do\r\n  rio clip wgs84.tif $(mercantile quadkey \"$tile\").tif --bounds \"$(mercantile shapes --extents \"$tile\")\"\r\ndone < z10.txt\r\n```\r\n\r\nThis results in\r\n- many raster images of pixel size 2857x1744\r\n- some raster images (at the borders) with smaller dimensions; the bounds are not filled with nodata\r\n\r\nShould rio clip use boundless windows and fill with nodata, to respect the user's bounds?\r\n\r\n(rio 1.1.3, tested in ubuntu 18.04 docker container with python 3.6)\n", "before_files": [{"content": "\"\"\"File translation command\"\"\"\n\nimport logging\n\nimport click\nfrom cligj import format_opt\n\nfrom .helpers import resolve_inout\nfrom . import options\nimport rasterio\nfrom rasterio.coords import disjoint_bounds\nfrom rasterio.crs import CRS\nfrom rasterio.windows import Window\n\n\nlogger = logging.getLogger(__name__)\n\n\n# Geographic (default), projected, or Mercator switch.\nprojection_geographic_opt = click.option(\n    '--geographic',\n    'projection',\n    flag_value='geographic',\n    help=\"Bounds in geographic coordinates.\")\n\nprojection_projected_opt = click.option(\n    '--projected',\n    'projection',\n    flag_value='projected',\n    default=True,\n    help=\"Bounds in input's own projected coordinates (the default).\")\n\n\n# Clip command\n@click.command(short_help='Clip a raster to given bounds.')\n@click.argument(\n    'files',\n    nargs=-1,\n    type=click.Path(),\n    required=True,\n    metavar=\"INPUT OUTPUT\")\n@options.output_opt\n@options.bounds_opt\n@click.option(\n    '--like',\n    type=click.Path(exists=True),\n    help='Raster dataset to use as a template for bounds')\n@format_opt\n@projection_geographic_opt\n@projection_projected_opt\n@options.overwrite_opt\n@options.creation_options\n@click.pass_context\ndef clip(ctx, files, output, bounds, like, driver, projection,\n         overwrite, creation_options):\n    \"\"\"Clips a raster using projected or geographic bounds.\n\n    \\b\n      $ rio clip input.tif output.tif --bounds xmin ymin xmax ymax\n      $ rio clip input.tif output.tif --like template.tif\n\n    The values of --bounds are presumed to be from the coordinate\n    reference system of the input dataset unless the --geographic option\n    is used, in which case the values may be longitude and latitude\n    bounds. Either JSON, for example \"[west, south, east, north]\", or\n    plain text \"west south east north\" representations of a bounding box\n    are acceptable.\n\n    If using --like, bounds will automatically be transformed to match the\n    coordinate reference system of the input.\n\n    It can also be combined to read bounds of a feature dataset using Fiona:\n\n    \\b\n      $ rio clip input.tif output.tif --bounds $(fio info features.shp --bounds)\n\n    \"\"\"\n    from rasterio.warp import transform_bounds\n\n    with ctx.obj['env']:\n\n        output, files = resolve_inout(files=files, output=output, overwrite=overwrite)\n        input = files[0]\n\n        with rasterio.open(input) as src:\n            if bounds:\n                if projection == 'geographic':\n                    bounds = transform_bounds(CRS.from_epsg(4326), src.crs, *bounds)\n                if disjoint_bounds(bounds, src.bounds):\n                    raise click.BadParameter('must overlap the extent of '\n                                             'the input raster',\n                                             param='--bounds',\n                                             param_hint='--bounds')\n            elif like:\n                with rasterio.open(like) as template_ds:\n                    bounds = template_ds.bounds\n                    if template_ds.crs != src.crs:\n                        bounds = transform_bounds(template_ds.crs, src.crs,\n                                                  *bounds)\n\n                    if disjoint_bounds(bounds, src.bounds):\n                        raise click.BadParameter('must overlap the extent of '\n                                                 'the input raster',\n                                                 param='--like',\n                                                 param_hint='--like')\n\n            else:\n                raise click.UsageError('--bounds or --like required')\n\n            bounds_window = src.window(*bounds)\n            bounds_window = bounds_window.intersection(\n                Window(0, 0, src.width, src.height))\n\n            # Get the window with integer height\n            # and width that contains the bounds window.\n            out_window = bounds_window.round_lengths(op='ceil')\n\n            height = int(out_window.height)\n            width = int(out_window.width)\n\n            out_kwargs = src.profile\n            out_kwargs.update({\n                'driver': driver,\n                'height': height,\n                'width': width,\n                'transform': src.window_transform(out_window)})\n            out_kwargs.update(**creation_options)\n\n            if 'blockxsize' in out_kwargs and out_kwargs['blockxsize'] > width:\n                del out_kwargs['blockxsize']\n                logger.warning(\"Blockxsize removed from creation options to accomodate small output width\")\n            if 'blockysize' in out_kwargs and out_kwargs['blockysize'] > height:\n                del out_kwargs['blockysize']\n                logger.warning(\"Blockysize removed from creation options to accomodate small output height\")\n\n            with rasterio.open(output, 'w', **out_kwargs) as out:\n                out.write(src.read(window=out_window,\n                                   out_shape=(src.count, height, width)))\n", "path": "rasterio/rio/clip.py"}], "after_files": [{"content": "\"\"\"File translation command\"\"\"\n\nimport logging\n\nimport click\nfrom cligj import format_opt\n\nfrom .helpers import resolve_inout\nfrom . import options\nimport rasterio\nfrom rasterio.coords import disjoint_bounds\nfrom rasterio.crs import CRS\nfrom rasterio.windows import Window\n\n\nlogger = logging.getLogger(__name__)\n\n\n# Geographic (default), projected, or Mercator switch.\nprojection_geographic_opt = click.option(\n    '--geographic',\n    'projection',\n    flag_value='geographic',\n    help=\"Bounds in geographic coordinates.\")\n\nprojection_projected_opt = click.option(\n    '--projected',\n    'projection',\n    flag_value='projected',\n    default=True,\n    help=\"Bounds in input's own projected coordinates (the default).\")\n\n\n# Clip command\n@click.command(short_help='Clip a raster to given bounds.')\n@click.argument(\n    'files',\n    nargs=-1,\n    type=click.Path(),\n    required=True,\n    metavar=\"INPUT OUTPUT\")\n@options.output_opt\n@options.bounds_opt\n@click.option(\n    '--like',\n    type=click.Path(exists=True),\n    help='Raster dataset to use as a template for bounds')\n@format_opt\n@projection_geographic_opt\n@projection_projected_opt\n@options.overwrite_opt\n@options.creation_options\n@click.option(\n    \"--with-complement/--without-complement\",\n    default=False,\n    help=\"Include the relative complement of the raster in the given bounds (giving a larger result), else return results only from the intersection of the raster and the bounds (the default).\",\n)\n@click.pass_context\ndef clip(\n    ctx,\n    files,\n    output,\n    bounds,\n    like,\n    driver,\n    projection,\n    overwrite,\n    creation_options,\n    with_complement,\n):\n    \"\"\"Clips a raster using projected or geographic bounds.\n\n    \\b\n      $ rio clip input.tif output.tif --bounds xmin ymin xmax ymax\n      $ rio clip input.tif output.tif --like template.tif\n\n    The values of --bounds are presumed to be from the coordinate\n    reference system of the input dataset unless the --geographic option\n    is used, in which case the values may be longitude and latitude\n    bounds. Either JSON, for example \"[west, south, east, north]\", or\n    plain text \"west south east north\" representations of a bounding box\n    are acceptable.\n\n    If using --like, bounds will automatically be transformed to match the\n    coordinate reference system of the input.\n\n    It can also be combined to read bounds of a feature dataset using Fiona:\n\n    \\b\n      $ rio clip input.tif output.tif --bounds $(fio info features.shp --bounds)\n\n    \"\"\"\n    from rasterio.warp import transform_bounds\n\n    with ctx.obj['env']:\n\n        output, files = resolve_inout(files=files, output=output, overwrite=overwrite)\n        input = files[0]\n\n        with rasterio.open(input) as src:\n            if bounds:\n                if projection == 'geographic':\n                    bounds = transform_bounds(CRS.from_epsg(4326), src.crs, *bounds)\n                if disjoint_bounds(bounds, src.bounds):\n                    raise click.BadParameter('must overlap the extent of '\n                                             'the input raster',\n                                             param='--bounds',\n                                             param_hint='--bounds')\n            elif like:\n                with rasterio.open(like) as template_ds:\n                    bounds = template_ds.bounds\n                    if template_ds.crs != src.crs:\n                        bounds = transform_bounds(template_ds.crs, src.crs,\n                                                  *bounds)\n\n                    if disjoint_bounds(bounds, src.bounds):\n                        raise click.BadParameter('must overlap the extent of '\n                                                 'the input raster',\n                                                 param='--like',\n                                                 param_hint='--like')\n\n            else:\n                raise click.UsageError('--bounds or --like required')\n\n            bounds_window = src.window(*bounds)\n\n            if not with_complement:\n                bounds_window = bounds_window.intersection(\n                    Window(0, 0, src.width, src.height)\n                )\n\n            # Get the window with integer height\n            # and width that contains the bounds window.\n            out_window = bounds_window.round_lengths(op='ceil')\n\n            height = int(out_window.height)\n            width = int(out_window.width)\n\n            out_kwargs = src.profile\n            out_kwargs.update({\n                'driver': driver,\n                'height': height,\n                'width': width,\n                'transform': src.window_transform(out_window)})\n            out_kwargs.update(**creation_options)\n\n            if 'blockxsize' in out_kwargs and out_kwargs['blockxsize'] > width:\n                del out_kwargs['blockxsize']\n                logger.warning(\"Blockxsize removed from creation options to accomodate small output width\")\n            if 'blockysize' in out_kwargs and out_kwargs['blockysize'] > height:\n                del out_kwargs['blockysize']\n                logger.warning(\"Blockysize removed from creation options to accomodate small output height\")\n\n            with rasterio.open(output, \"w\", **out_kwargs) as out:\n                out.write(\n                    src.read(\n                        window=out_window,\n                        out_shape=(src.count, height, width),\n                        boundless=True,\n                    )\n                )\n", "path": "rasterio/rio/clip.py"}]}