prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Add `GetMetadataItem` like method 
  Ref: https://github.com/mapbox/rasterio/issues/1077, 
  
  I'm proposing to add a new method in https://github.com/mapbox/rasterio/blob/master/rasterio/_base.pyx to replicate GDAL GetMetadataItem
  
  
  **Method Name:** `get_metadata_item` or `get_metadata`
  **Why:** I need to be able to get TIFF metadata like `band.GetMetadataItem('IFD_OFFSET', 'TIFF')`
  
  **Code:**
  
  ```cython
      def get_metadata(self, bidx, ns, dm=None, ovr=None):
          """Returns metadata item
  
          Parameters
          ----------
          bidx: int
              Band index, starting with 1.
          name: str
              The key for the metadata item to fetch.
          domain: str
              The domain to fetch for.
          ovr: int
              Overview level
  
          Returns
          -------
          str
          """
          cdef GDALMajorObjectH b = NULL
          cdef GDALMajorObjectH obj = NULL
          cdef char *value = NULL
          cdef const char *name = NULL
          cdef const char *domain = NULL
  
          ns = ns.encode('utf-8')
          name = ns
  
          if dm:
              dm = dm.encode('utf-8')
              domain = dm
  
          b = self.band(bidx)
          if ovr:
              b = GDALGetOverview(b, ovr)
  
          obj = b
  
          value = GDALGetMetadataItem(obj, name, domain)
          if value == NULL:
              return None
          else:
              return value
  ```
  
  @sgillies I'm happy to submit a PR for that :-) 
  
  </issue>
  <code>
  [start of rasterio/errors.py]
  1 """Errors and Warnings."""
  2 
  3 from click import FileError
  4 
  5 
  6 class RasterioError(Exception):
  7     """Root exception class"""
  8 
  9 
  10 class WindowError(RasterioError):
  11     """Raised when errors occur during window operations"""
  12 
  13 
  14 class CRSError(ValueError):
  15     """Raised when a CRS string or mapping is invalid or cannot serve
  16     to define a coordinate transformation."""
  17 
  18 
  19 class EnvError(RasterioError):
  20     """Raised when the state of GDAL/AWS environment cannot be created
  21     or modified."""
  22 
  23 
  24 class DriverRegistrationError(ValueError):
  25     """Raised when a format driver is requested but is not registered."""
  26 
  27 
  28 class FileOverwriteError(FileError):
  29     """Raised when Rasterio's CLI refuses to clobber output files."""
  30 
  31     def __init__(self, message):
  32         """Raise FileOverwriteError with message as hint."""
  33         super(FileOverwriteError, self).__init__('', hint=message)
  34 
  35 
  36 class RasterioIOError(IOError):
  37     """Raised when a dataset cannot be opened using one of the
  38     registered format drivers."""
  39 
  40 
  41 class NodataShadowWarning(UserWarning):
  42     """Warn that a dataset's nodata attribute is shadowing its alpha band."""
  43 
  44     def __str__(self):
  45         return ("The dataset's nodata attribute is shadowing "
  46                 "the alpha band. All masks will be determined "
  47                 "by the nodata attribute")
  48 
  49 
  50 class NotGeoreferencedWarning(UserWarning):
  51     """Warn that a dataset isn't georeferenced."""
  52 
  53 
  54 class GDALBehaviorChangeException(RuntimeError):
  55     """Raised when GDAL's behavior differs from the given arguments.  For
  56     example, antimeridian cutting is always on as of GDAL 2.2.0.  Users
  57     expecting it to be off will be presented with a MultiPolygon when the
  58     rest of their code expects a Polygon.
  59 
  60         # Raises an exception on GDAL >= 2.2.0
  61         rasterio.warp.transform_geometry(
  62             src_crs, dst_crs, antimeridian_cutting=False)
  63     """
  64 
  65 
  66 class GDALOptionNotImplementedError(RasterioError):
  67     """A dataset opening or dataset creation option can't be supported
  68 
  69     This will be raised from Rasterio's shim modules. For example, when
  70     a user passes arguments to open_dataset() that can't be evaluated
  71     by GDAL 1.x.
  72     """
  73 
  74 class GDALVersionError(RasterioError):
  75     """Raised if the runtime version of GDAL does not meet the required
  76     version of GDAL."""
  77 
  78 
  79 class WindowEvaluationError(ValueError):
  80     """Raised when window evaluation fails"""
  81 
  82 
  83 class RasterioDeprecationWarning(UserWarning):
  84     """Rasterio module deprecations"""
  85 
  86 
  87 class RasterBlockError(RasterioError):
  88     """Raised when raster block access fails"""
  89
  [end of rasterio/errors.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/rasterio/errors.py b/rasterio/errors.py
  --- a/rasterio/errors.py
  +++ b/rasterio/errors.py
  @@ -86,3 +86,7 @@
   
   class RasterBlockError(RasterioError):
       """Raised when raster block access fails"""
  +
  +
  +class BandOverviewError(UserWarning):
  +    """Raised when a band overview access fails."""
  
verification_info: {"golden_diff": "diff --git a/rasterio/errors.py b/rasterio/errors.py\n--- a/rasterio/errors.py\n+++ b/rasterio/errors.py\n@@ -86,3 +86,7 @@\n \n class RasterBlockError(RasterioError):\n     \"\"\"Raised when raster block access fails\"\"\"\n+\n+\n+class BandOverviewError(UserWarning):\n+    \"\"\"Raised when a band overview access fails.\"\"\"\n", "issue": "Add `GetMetadataItem` like method \nRef: https://github.com/mapbox/rasterio/issues/1077, \r\n\r\nI'm proposing to add a new method in https://github.com/mapbox/rasterio/blob/master/rasterio/_base.pyx to replicate GDAL GetMetadataItem\r\n\r\n\r\n**Method Name:** `get_metadata_item` or `get_metadata`\r\n**Why:** I need to be able to get TIFF metadata like `band.GetMetadataItem('IFD_OFFSET', 'TIFF')`\r\n\r\n**Code:**\r\n\r\n```cython\r\n    def get_metadata(self, bidx, ns, dm=None, ovr=None):\r\n        \"\"\"Returns metadata item\r\n\r\n        Parameters\r\n        ----------\r\n        bidx: int\r\n            Band index, starting with 1.\r\n        name: str\r\n            The key for the metadata item to fetch.\r\n        domain: str\r\n            The domain to fetch for.\r\n        ovr: int\r\n            Overview level\r\n\r\n        Returns\r\n        -------\r\n        str\r\n        \"\"\"\r\n        cdef GDALMajorObjectH b = NULL\r\n        cdef GDALMajorObjectH obj = NULL\r\n        cdef char *value = NULL\r\n        cdef const char *name = NULL\r\n        cdef const char *domain = NULL\r\n\r\n        ns = ns.encode('utf-8')\r\n        name = ns\r\n\r\n        if dm:\r\n            dm = dm.encode('utf-8')\r\n            domain = dm\r\n\r\n        b = self.band(bidx)\r\n        if ovr:\r\n            b = GDALGetOverview(b, ovr)\r\n\r\n        obj = b\r\n\r\n        value = GDALGetMetadataItem(obj, name, domain)\r\n        if value == NULL:\r\n            return None\r\n        else:\r\n            return value\r\n```\r\n\r\n@sgillies I'm happy to submit a PR for that :-) \n", "before_files": [{"content": "\"\"\"Errors and Warnings.\"\"\"\n\nfrom click import FileError\n\n\nclass RasterioError(Exception):\n    \"\"\"Root exception class\"\"\"\n\n\nclass WindowError(RasterioError):\n    \"\"\"Raised when errors occur during window operations\"\"\"\n\n\nclass CRSError(ValueError):\n    \"\"\"Raised when a CRS string or mapping is invalid or cannot serve\n    to define a coordinate transformation.\"\"\"\n\n\nclass EnvError(RasterioError):\n    \"\"\"Raised when the state of GDAL/AWS environment cannot be created\n    or modified.\"\"\"\n\n\nclass DriverRegistrationError(ValueError):\n    \"\"\"Raised when a format driver is requested but is not registered.\"\"\"\n\n\nclass FileOverwriteError(FileError):\n    \"\"\"Raised when Rasterio's CLI refuses to clobber output files.\"\"\"\n\n    def __init__(self, message):\n        \"\"\"Raise FileOverwriteError with message as hint.\"\"\"\n        super(FileOverwriteError, self).__init__('', hint=message)\n\n\nclass RasterioIOError(IOError):\n    \"\"\"Raised when a dataset cannot be opened using one of the\n    registered format drivers.\"\"\"\n\n\nclass NodataShadowWarning(UserWarning):\n    \"\"\"Warn that a dataset's nodata attribute is shadowing its alpha band.\"\"\"\n\n    def __str__(self):\n        return (\"The dataset's nodata attribute is shadowing \"\n                \"the alpha band. All masks will be determined \"\n                \"by the nodata attribute\")\n\n\nclass NotGeoreferencedWarning(UserWarning):\n    \"\"\"Warn that a dataset isn't georeferenced.\"\"\"\n\n\nclass GDALBehaviorChangeException(RuntimeError):\n    \"\"\"Raised when GDAL's behavior differs from the given arguments.  For\n    example, antimeridian cutting is always on as of GDAL 2.2.0.  Users\n    expecting it to be off will be presented with a MultiPolygon when the\n    rest of their code expects a Polygon.\n\n        # Raises an exception on GDAL >= 2.2.0\n        rasterio.warp.transform_geometry(\n            src_crs, dst_crs, antimeridian_cutting=False)\n    \"\"\"\n\n\nclass GDALOptionNotImplementedError(RasterioError):\n    \"\"\"A dataset opening or dataset creation option can't be supported\n\n    This will be raised from Rasterio's shim modules. For example, when\n    a user passes arguments to open_dataset() that can't be evaluated\n    by GDAL 1.x.\n    \"\"\"\n\nclass GDALVersionError(RasterioError):\n    \"\"\"Raised if the runtime version of GDAL does not meet the required\n    version of GDAL.\"\"\"\n\n\nclass WindowEvaluationError(ValueError):\n    \"\"\"Raised when window evaluation fails\"\"\"\n\n\nclass RasterioDeprecationWarning(UserWarning):\n    \"\"\"Rasterio module deprecations\"\"\"\n\n\nclass RasterBlockError(RasterioError):\n    \"\"\"Raised when raster block access fails\"\"\"\n", "path": "rasterio/errors.py"}]}