prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Check for "ndarray-like" instead of ndarray in _warp; other places
  I want to use `rasterio.warp.reproject` on an `xray.Dataset` with `xray.Dataset.apply` (http://xray.readthedocs.org/en/stable/). xray has a feature to turn the dataset into a `np.ndarray`, but that means losing all my metadata.
  
  At https://github.com/mapbox/rasterio/blob/master/rasterio/_warp.pyx#L249, _warp checks that the source is an `np.ndarray` (whereas the source in my case is an `xray.DataArray` - satisfying the same interfaces as `np.ndarray`), so I get an invalid source error.
  
  It could be a good idea to check for something like
  
  ```
  def is_ndarray_like(source):
      return hasattr(source, '__array__')
  ```
  
  instead of
  
  ```
  isinstance(source, np.ndarray)
  ```
  
  so other numpy-like arrays can be used.
  
  
  </issue>
  <code>
  [start of rasterio/dtypes.py]
  1 # Mapping of GDAL to Numpy data types.
  2 #
  3 # Since 0.13 we are not importing numpy here and data types are strings.
  4 # Happily strings can be used throughout Numpy and so existing code will
  5 # break.
  6 #
  7 # Within Rasterio, to test data types, we use Numpy's dtype() factory to 
  8 # do something like this:
  9 #
  10 #   if np.dtype(destination.dtype) == np.dtype(rasterio.uint8): ...
  11 #
  12 
  13 bool_ = 'bool'
  14 ubyte = uint8 = 'uint8'
  15 uint16 = 'uint16'
  16 int16 = 'int16'
  17 uint32 = 'uint32'
  18 int32 = 'int32'
  19 float32 = 'float32'
  20 float64 = 'float64'
  21 complex_ = 'complex'
  22 complex64 = 'complex64'
  23 complex128 = 'complex128'
  24 
  25 # Not supported:
  26 #  GDT_CInt16 = 8, GDT_CInt32 = 9, GDT_CFloat32 = 10, GDT_CFloat64 = 11
  27 
  28 dtype_fwd = {
  29     0: None,            # GDT_Unknown
  30     1: ubyte,           # GDT_Byte
  31     2: uint16,          # GDT_UInt16
  32     3: int16,           # GDT_Int16
  33     4: uint32,          # GDT_UInt32
  34     5: int32,           # GDT_Int32
  35     6: float32,         # GDT_Float32
  36     7: float64,         # GDT_Float64
  37     8: complex_,        # GDT_CInt16
  38     9: complex_,        # GDT_CInt32
  39     10: complex64,      # GDT_CFloat32
  40     11: complex128 }    # GDT_CFloat64
  41 
  42 dtype_rev = dict((v, k) for k, v in dtype_fwd.items())
  43 dtype_rev['uint8'] = 1
  44 
  45 typename_fwd = {
  46     0: 'Unknown',
  47     1: 'Byte',
  48     2: 'UInt16',
  49     3: 'Int16',
  50     4: 'UInt32',
  51     5: 'Int32',
  52     6: 'Float32',
  53     7: 'Float64',
  54     8: 'CInt16',
  55     9: 'CInt32',
  56     10: 'CFloat32',
  57     11: 'CFloat64' }
  58 
  59 typename_rev = dict((v, k) for k, v in typename_fwd.items())
  60 
  61 def _gdal_typename(dt):
  62     try:
  63         return typename_fwd[dtype_rev[dt]]
  64     except KeyError:
  65         return typename_fwd[dtype_rev[dt().dtype.name]]
  66 
  67 def check_dtype(dt):
  68     if dt not in dtype_rev:
  69         try:
  70             return dt().dtype.name in dtype_rev
  71         except:
  72             return False
  73     return True
  74 
  75 
  76 def get_minimum_int_dtype(values):
  77     """
  78     Uses range checking to determine the minimum integer data type required
  79     to represent values.
  80 
  81     :param values: numpy array
  82     :return: named data type that can be later used to create a numpy dtype
  83     """
  84 
  85     min_value = values.min()
  86     max_value = values.max()
  87     
  88     if min_value >= 0:
  89         if max_value <= 255:
  90             return uint8
  91         elif max_value <= 65535:
  92             return uint16
  93         elif max_value <= 4294967295:
  94             return uint32
  95     elif min_value >= -32768 and max_value <= 32767:
  96         return int16
  97     elif min_value >= -2147483648 and max_value <= 2147483647:
  98         return int32
  99
  [end of rasterio/dtypes.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/dtypes.py b/rasterio/dtypes.py
  --- a/rasterio/dtypes.py
  +++ b/rasterio/dtypes.py
  @@ -96,3 +96,9 @@
           return int16
       elif min_value >= -2147483648 and max_value <= 2147483647:
           return int32
  +
  +
  +def is_ndarray(array):
  +    import numpy
  +
  +    return isinstance(array, numpy.ndarray) or hasattr(array, '__array__')
  
verification_info: {"golden_diff": "diff --git a/rasterio/dtypes.py b/rasterio/dtypes.py\n--- a/rasterio/dtypes.py\n+++ b/rasterio/dtypes.py\n@@ -96,3 +96,9 @@\n         return int16\n     elif min_value >= -2147483648 and max_value <= 2147483647:\n         return int32\n+\n+\n+def is_ndarray(array):\n+    import numpy\n+\n+    return isinstance(array, numpy.ndarray) or hasattr(array, '__array__')\n", "issue": "Check for \"ndarray-like\" instead of ndarray in _warp; other places\nI want to use `rasterio.warp.reproject` on an `xray.Dataset` with `xray.Dataset.apply` (http://xray.readthedocs.org/en/stable/). xray has a feature to turn the dataset into a `np.ndarray`, but that means losing all my metadata.\n\nAt https://github.com/mapbox/rasterio/blob/master/rasterio/_warp.pyx#L249, _warp checks that the source is an `np.ndarray` (whereas the source in my case is an `xray.DataArray` - satisfying the same interfaces as `np.ndarray`), so I get an invalid source error.\n\nIt could be a good idea to check for something like\n\n```\ndef is_ndarray_like(source):\n    return hasattr(source, '__array__')\n```\n\ninstead of\n\n```\nisinstance(source, np.ndarray)\n```\n\nso other numpy-like arrays can be used.\n\n", "before_files": [{"content": "# Mapping of GDAL to Numpy data types.\n#\n# Since 0.13 we are not importing numpy here and data types are strings.\n# Happily strings can be used throughout Numpy and so existing code will\n# break.\n#\n# Within Rasterio, to test data types, we use Numpy's dtype() factory to \n# do something like this:\n#\n#   if np.dtype(destination.dtype) == np.dtype(rasterio.uint8): ...\n#\n\nbool_ = 'bool'\nubyte = uint8 = 'uint8'\nuint16 = 'uint16'\nint16 = 'int16'\nuint32 = 'uint32'\nint32 = 'int32'\nfloat32 = 'float32'\nfloat64 = 'float64'\ncomplex_ = 'complex'\ncomplex64 = 'complex64'\ncomplex128 = 'complex128'\n\n# Not supported:\n#  GDT_CInt16 = 8, GDT_CInt32 = 9, GDT_CFloat32 = 10, GDT_CFloat64 = 11\n\ndtype_fwd = {\n    0: None,            # GDT_Unknown\n    1: ubyte,           # GDT_Byte\n    2: uint16,          # GDT_UInt16\n    3: int16,           # GDT_Int16\n    4: uint32,          # GDT_UInt32\n    5: int32,           # GDT_Int32\n    6: float32,         # GDT_Float32\n    7: float64,         # GDT_Float64\n    8: complex_,        # GDT_CInt16\n    9: complex_,        # GDT_CInt32\n    10: complex64,      # GDT_CFloat32\n    11: complex128 }    # GDT_CFloat64\n\ndtype_rev = dict((v, k) for k, v in dtype_fwd.items())\ndtype_rev['uint8'] = 1\n\ntypename_fwd = {\n    0: 'Unknown',\n    1: 'Byte',\n    2: 'UInt16',\n    3: 'Int16',\n    4: 'UInt32',\n    5: 'Int32',\n    6: 'Float32',\n    7: 'Float64',\n    8: 'CInt16',\n    9: 'CInt32',\n    10: 'CFloat32',\n    11: 'CFloat64' }\n\ntypename_rev = dict((v, k) for k, v in typename_fwd.items())\n\ndef _gdal_typename(dt):\n    try:\n        return typename_fwd[dtype_rev[dt]]\n    except KeyError:\n        return typename_fwd[dtype_rev[dt().dtype.name]]\n\ndef check_dtype(dt):\n    if dt not in dtype_rev:\n        try:\n            return dt().dtype.name in dtype_rev\n        except:\n            return False\n    return True\n\n\ndef get_minimum_int_dtype(values):\n    \"\"\"\n    Uses range checking to determine the minimum integer data type required\n    to represent values.\n\n    :param values: numpy array\n    :return: named data type that can be later used to create a numpy dtype\n    \"\"\"\n\n    min_value = values.min()\n    max_value = values.max()\n    \n    if min_value >= 0:\n        if max_value <= 255:\n            return uint8\n        elif max_value <= 65535:\n            return uint16\n        elif max_value <= 4294967295:\n            return uint32\n    elif min_value >= -32768 and max_value <= 32767:\n        return int16\n    elif min_value >= -2147483648 and max_value <= 2147483647:\n        return int32\n", "path": "rasterio/dtypes.py"}]}