Repository: mars-project/mars

Issue:
[BUG] Cannot pass numpy array into mt.swapaxes
<!--
Thank you for your contribution!

Please review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.
-->

## Describe the bug
I met a bug when i passed numpy array into `mt.swapaxes`. See below:
```
In [35]: p = np.random.rand(3,4,5)                                                                                                                                                                   

In [36]: mt.swapaxes(p, 0, -1)                                                                                                                                                                       
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-36-016cb9916fdb> in <module>
----> 1 mt.swapaxes(p, 0, -1)

~/anaconda3/envs/pymars0.6/lib/python3.7/site-packages/mars/tensor/base/swapaxes.py in swapaxes(a, axis1, axis2)
    150         return a
    151 
--> 152     op = TensorSwapAxes(axis1, axis2, dtype=a.dtype, sparse=a.issparse())
    153     return op(a)

AttributeError: 'numpy.ndarray' object has no attribute 'issparse'
```



Discussion:
Are you interested in fixing it on your own? I guess it's pretty simple for you.

Resolving patch:
diff --git a/mars/tensor/base/swapaxes.py b/mars/tensor/base/swapaxes.py
--- a/mars/tensor/base/swapaxes.py
+++ b/mars/tensor/base/swapaxes.py
@@ -16,10 +16,11 @@
 
 from ... import opcodes as OperandDef
 from ...serialize import KeyField, Int32Field
-from ..utils import validate_axis, reverse_order
-from ..operands import TensorHasInput, TensorOperandMixin
 from ..array_utils import as_same_device, device
 from ..core import TensorOrder
+from ..datasource import tensor as astensor
+from ..operands import TensorHasInput, TensorOperandMixin
+from ..utils import validate_axis, reverse_order
 
 
 def _swap(it, axis1, axis2):
@@ -143,6 +144,7 @@ def swapaxes(a, axis1, axis2):
             [3, 7]]])
 
     """
+    a = astensor(a)
     axis1 = validate_axis(a.ndim, axis1)
     axis2 = validate_axis(a.ndim, axis2)
 


Test patch:
diff --git a/mars/tensor/base/tests/test_base_execute.py b/mars/tensor/base/tests/test_base_execute.py
--- a/mars/tensor/base/tests/test_base_execute.py
+++ b/mars/tensor/base/tests/test_base_execute.py
@@ -19,14 +19,14 @@
 import pandas as pd
 
 from mars import tensor as mt
-from mars.tiles import get_tiled
-from mars.tensor.datasource import tensor, ones, zeros, arange
 from mars.tensor.base import copyto, transpose, moveaxis, broadcast_to, broadcast_arrays, where, \
     expand_dims, rollaxis, atleast_1d, atleast_2d, atleast_3d, argwhere, array_split, split, \
     hsplit, vsplit, dsplit, roll, squeeze, diff, ediff1d, flip, flipud, fliplr, repeat, tile, \
     isin, searchsorted, unique, sort, argsort, partition, argpartition, topk, argtopk, \
-    trapz, shape, to_gpu, to_cpu
+    trapz, shape, to_gpu, to_cpu, swapaxes
+from mars.tensor.datasource import tensor, ones, zeros, arange
 from mars.tests.core import require_cupy, ExecutorForTest, TestBase
+from mars.tiles import get_tiled
 
 
 class Test(TestBase):
@@ -143,6 +143,13 @@ def testTransposeExecution(self):
         self.assertEqual(res.flags['F_CONTIGUOUS'], expected.flags['F_CONTIGUOUS'])
 
     def testSwapaxesExecution(self):
+        raw = np.random.random((11, 8, 5))
+        arr = swapaxes(raw, 2, 0)
+
+        res = self.executor.execute_tensor(arr, concat=True)
+
+        np.testing.assert_array_equal(res[0], raw.swapaxes(2, 0))
+
         raw = np.random.random((11, 8, 5))
         arr = tensor(raw, chunk_size=3)
         arr2 = arr.swapaxes(2, 0)
@@ -444,13 +451,13 @@ def testArraySplitExecution(self):
         [np.testing.assert_equal(r, e) for r, e in zip(res, expected)]
 
     def testSplitExecution(self):
-        for a in ((1,1,1,2,2,3), [1,1,1,2,2,3]):
-            splits = split(a, (3,5))
+        for a in ((1, 1, 1, 2, 2, 3), [1, 1, 1, 2, 2, 3]):
+            splits = split(a, (3, 5))
             self.assertEqual(len(splits), 3)
             splits0 = self.executor.execute_tensor(splits[0], concat=True)[0]
-            np.testing.assert_array_equal(splits0, (1,1,1))
+            np.testing.assert_array_equal(splits0, (1, 1, 1))
             splits1 = self.executor.execute_tensor(splits[1], concat=True)[0]
-            np.testing.assert_array_equal(splits1, (2,2))
+            np.testing.assert_array_equal(splits1, (2, 2))
             splits2 = self.executor.execute_tensor(splits[2], concat=True)[0]
             np.testing.assert_array_equal(splits2, (3,))