Repository: numba/numba

Issue:
np.eye() does not support dtype argument, which is not stated in the docs and does not return meaningful error code
## Reporting a bug


- Version 0.36.2
- np.eye() does not support the dtype argument, which is not stated in the docs and does not return a meaningful error code

`import numpy as np`
`import numba as nb`

`@nb.jit(nb.float32[:,:](nb.int64),nopython=True)`
`def eye(n):`
`    out = np.eye(n,dtype=np.float32)`
`    return out`




Discussion:
Thanks for the report. The doc for `numpy.eye()` clearly needs updating. As to meaningful errors, I'd really recommend updating your Numba installation to version 0.39 (latest), 0.38 got a large rewrite of the error reporting code and 0.39 got even more! For me, on 0.39 I get:
```python
numba.errors.TypingError: Failed at nopython (nopython frontend)
Invalid usage of Function(<function eye at 0x7f812b665730>) with parameters (int64, dtype=class(float32))
 * parameterized
In definition 0:
    TypingError: unsupported call signature
    raised from<path>/numba/typing/templates.py:263
[1] During: resolving callee type: Function(<function eye at 0x7f812b665730>)
[2] During: typing of call at issue3159.py (6)


File "issue3159.py", line 6:
def eye(n):
    out = np.eye(n,dtype=np.float32)
    ^
```
I've also updated this in the current development work for 0.40 so it says:
```python
numba.errors.TypingError: Failed at nopython (nopython frontend)
Invalid use of Function(<function eye at 0x7f590fec6730>) with argument(s) of type(s): (int64, dtype=class(float32))
 * parameterized
In definition 0:
    TypingError: unsupported call signature
    raised from <path>/numba/typing/templates.py:263
This error is usually caused by passing an argument of a type that is unsupported by the named function.
[1] During: resolving callee type: Function(<function eye at 0x7f590fec6730>)
[2] During: typing of call at issue3159.py (6)


File "issue3159.py", line 6:
def eye(n):
    out = np.eye(n,dtype=np.float32)
```
which has the included hint:
```
This error is usually caused by passing an argument of a type that is unsupported by the named function.
```
Also if you install `colorama`, the error messages are color highlighted. If you decide to update, please let us know what you think, we are always interested in feedback.
Thanks for the reply. Unfortunately, I cannot update, because anaconda won't let me, but the new error message would have helped me a lot. Thanks!
I'm also having this problem (I need to instantiate a `np.complex128` matrix with `np.eye()`). What is the best workaround for this?
You can use np.zeros and set the diagonal manually.

Resolving patch:
diff --git a/numba/targets/arrayobj.py b/numba/targets/arrayobj.py
--- a/numba/targets/arrayobj.py
+++ b/numba/targets/arrayobj.py
@@ -3427,52 +3427,44 @@ def identity(n, dtype):
     return impl_ret_new_ref(context, builder, sig.return_type, res)
 
 
-@lower_builtin(np.eye, types.Integer)
-def numpy_eye(context, builder, sig, args):
-
-    def eye(n):
-        return np.identity(n)
-
-    res = context.compile_internal(builder, eye, sig, args)
-    return impl_ret_new_ref(context, builder, sig.return_type, res)
-
-@lower_builtin(np.eye, types.Integer, types.Integer)
-def numpy_eye(context, builder, sig, args):
-
-    def eye(n, m):
-        return np.eye(n, m, 0, np.float64)
-
-    res = context.compile_internal(builder, eye, sig, args)
-    return impl_ret_new_ref(context, builder, sig.return_type, res)
-
-@lower_builtin(np.eye, types.Integer, types.Integer,
-           types.Integer)
-def numpy_eye(context, builder, sig, args):
-
-    def eye(n, m, k):
-        return np.eye(n, m, k, np.float64)
+def _eye_none_handler(N, M):
+    pass
+
+@extending.overload(_eye_none_handler)
+def _eye_none_handler_impl(N, M):
+    if isinstance(M, types.NoneType):
+        def impl(N, M):
+            return N
+    else:
+        def impl(N, M):
+            return M
+    return impl
 
-    res = context.compile_internal(builder, eye, sig, args)
-    return impl_ret_new_ref(context, builder, sig.return_type, res)
+@extending.overload(np.eye)
+def numpy_eye(N, M=None, k=0, dtype=float):
 
-@lower_builtin(np.eye, types.Integer, types.Integer,
-           types.Integer, types.DTypeSpec)
-def numpy_eye(context, builder, sig, args):
+    if dtype is None or isinstance(dtype, types.NoneType):
+        dt = np.dtype(float)
+    elif isinstance(dtype, (types.DTypeSpec, types.Number)):
+        # dtype or instance of dtype
+        dt = as_dtype(getattr(dtype, 'dtype', dtype))
+    else:
+        dt = np.dtype(dtype)
 
-    def eye(n, m, k, dtype):
-        arr = np.zeros((n, m), dtype)
+    def impl(N, M=None, k=0, dtype=float):
+        _M =  _eye_none_handler(N, M)
+        arr = np.zeros((N, _M), dt)
         if k >= 0:
-            d = min(n, m - k)
+            d = min(N, _M - k)
             for i in range(d):
                 arr[i, i + k] = 1
         else:
-            d = min(n + k, m)
+            d = min(N + k, _M)
             for i in range(d):
                 arr[i - k, i] = 1
         return arr
+    return impl
 
-    res = context.compile_internal(builder, eye, sig, args)
-    return impl_ret_new_ref(context, builder, sig.return_type, res)
 
 @lower_builtin(np.diag, types.Array)
 def numpy_diag(context, builder, sig, args):
diff --git a/numba/typing/npydecl.py b/numba/typing/npydecl.py
--- a/numba/typing/npydecl.py
+++ b/numba/typing/npydecl.py
@@ -623,21 +623,6 @@ def _infer_dtype_from_inputs(inputs):
     return dtype
 
 
-@infer_global(np.eye)
-class NdEye(CallableTemplate):
-
-    def generic(self):
-        def typer(N, M=None, k=None, dtype=None):
-            if dtype is None:
-                nb_dtype = types.float64
-            else:
-                nb_dtype = _parse_dtype(dtype)
-            if nb_dtype is not None:
-                return types.Array(ndim=2, dtype=nb_dtype, layout='C')
-
-        return typer
-
-
 @infer_global(np.arange)
 class NdArange(AbstractTemplate):
 


Test patch:
diff --git a/numba/tests/test_dyn_array.py b/numba/tests/test_dyn_array.py
--- a/numba/tests/test_dyn_array.py
+++ b/numba/tests/test_dyn_array.py
@@ -873,6 +873,13 @@ def func(n):
             return np.eye(n)
         self.check_outputs(func, [(1,), (3,)])
 
+    def test_eye_n_dtype(self):
+        # check None option, dtype class, instance of dtype class
+        for dt in (None, np.complex128, np.complex64(1)):
+            def func(n, dtype=dt):
+                return np.eye(n, dtype=dtype)
+            self.check_outputs(func, [(1,), (3,)])
+
     def test_eye_n_m(self):
         def func(n, m):
             return np.eye(n, m)