Repository: chainer/chainer

Issue:
`cupy.ndarray.__ini__` doen't support `int` and `None` as its `shape`
`numpy.ndarray` supports `int` and `None` as its shape, but `cupy.ndarray` doesn't.

```
>>> numpy.ndarray(1)
array([ 0.])
>>> numpy.ndarray(None)
array(0.0)
```



Discussion:

Resolving patch:
diff --git a/cupy/__init__.py b/cupy/__init__.py
--- a/cupy/__init__.py
+++ b/cupy/__init__.py
@@ -66,6 +66,17 @@
 float64 = numpy.float64
 
 
+def _get_size(size):
+    if size is None:
+        return ()
+    elif isinstance(size, collections.Sequence):
+        return tuple(size)
+    elif isinstance(size, int):
+        return size,
+    else:
+        raise ValueError('size should be None, collections.Sequence, or int')
+
+
 class ndarray(object):
 
     """Multi-dimensional array on a CUDA device.
@@ -87,7 +98,7 @@ class ndarray(object):
 
     """
     def __init__(self, shape, dtype=float, memptr=None, strides=None):
-        self._shape = shape = tuple(shape)
+        self._shape = shape = _get_size(shape)
         self._dtype = dtype = numpy.dtype(dtype)
         size = 1
         for s in shape:
diff --git a/cupy/random/generator.py b/cupy/random/generator.py
--- a/cupy/random/generator.py
+++ b/cupy/random/generator.py
@@ -1,6 +1,5 @@
 import atexit
 import binascii
-import collections
 import os
 import time
 
@@ -62,7 +61,6 @@ def lognormal(self, mean=0.0, sigma=1.0, size=None, dtype=float):
 
         """
         dtype = _check_and_get_dtype(dtype)
-        size = _get_size(size)
         out = cupy.empty(size, dtype=dtype)
         if dtype.char == 'f':
             func = curand.generateLogNormal
@@ -80,7 +78,6 @@ def normal(self, loc=0.0, scale=1.0, size=None, dtype=float):
 
         """
         dtype = _check_and_get_dtype(dtype)
-        size = _get_size(size)
         out = cupy.empty(size, dtype=dtype)
         if dtype.char == 'f':
             func = curand.generateNormal
@@ -129,7 +126,6 @@ def random_sample(self, size=None, dtype=float):
 
         """
         dtype = _check_and_get_dtype(dtype)
-        size = _get_size(size)
         out = cupy.empty(size, dtype=dtype)
         if dtype.char == 'f':
             func = curand.generateUniform
@@ -177,7 +173,6 @@ def uniform(self, low=0.0, high=1.0, size=None, dtype=float):
 
         """
         dtype = numpy.dtype(dtype)
-        size = _get_size(size)
         rand = self.random_sample(size=size, dtype=dtype)
         return dtype.type(low) + rand * dtype.type(high - low)
 
@@ -231,17 +226,6 @@ def get_random_state():
     return rs
 
 
-def _get_size(size):
-    if size is None:
-        return ()
-    elif isinstance(size, collections.Sequence):
-        return tuple(size)
-    elif isinstance(size, int):
-        return size,
-    else:
-        raise ValueError('size should be None, collections.Sequence, or int')
-
-
 def _check_and_get_dtype(dtype):
     dtype = numpy.dtype(dtype)
     if dtype.char not in ('f', 'd'):


Test patch:
diff --git a/tests/cupy_tests/creation_tests/test_basic.py b/tests/cupy_tests/creation_tests/test_basic.py
--- a/tests/cupy_tests/creation_tests/test_basic.py
+++ b/tests/cupy_tests/creation_tests/test_basic.py
@@ -18,6 +18,20 @@ def test_empty(self, xp, dtype):
         a.fill(0)
         return a
 
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_array_equal()
+    def test_empty_scalar(self, xp, dtype):
+        a = xp.empty(None, dtype=dtype)
+        a.fill(0)
+        return a
+
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_array_equal()
+    def test_empty_int(self, xp, dtype):
+        a = xp.empty(3, dtype=dtype)
+        a.fill(0)
+        return a
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_array_equal()
     def test_empty_like(self, xp, dtype):
@@ -46,6 +60,16 @@ def test_identity(self, xp, dtype):
     def test_zeros(self, xp, dtype):
         return xp.zeros((2, 3, 4), dtype=dtype)
 
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_array_equal()
+    def test_zeros_scalar(self, xp, dtype):
+        return xp.zeros(None, dtype=dtype)
+
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_array_equal()
+    def test_zeros_int(self, xp, dtype):
+        return xp.zeros(3, dtype=dtype)
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_array_equal()
     def test_zeros_like(self, xp, dtype):
diff --git a/tests/cupy_tests/random_tests/test_generator.py b/tests/cupy_tests/random_tests/test_generator.py
--- a/tests/cupy_tests/random_tests/test_generator.py
+++ b/tests/cupy_tests/random_tests/test_generator.py
@@ -188,28 +188,6 @@ def test_get_random_state_with_chainer_seed(self):
         generator.RandomState.assert_called_with('1')
 
 
-class TestGetSize(unittest.TestCase):
-
-    def test_none(self):
-        self.assertEqual(generator._get_size(None), ())
-
-    def check_collection(self, a):
-        self.assertEqual(generator._get_size(a), tuple(a))
-
-    def test_list(self):
-        self.check_collection([1, 2, 3])
-
-    def test_tuple(self):
-        self.check_collection((1, 2, 3))
-
-    def test_int(self):
-        self.assertEqual(generator._get_size(1), (1,))
-
-    def test_float(self):
-        with self.assertRaises(ValueError):
-            generator._get_size(1.0)
-
-
 class TestCheckAndGetDtype(unittest.TestCase):
 
     @testing.for_float_dtypes(no_float16=True)
diff --git a/tests/cupy_tests/test_ndarray.py b/tests/cupy_tests/test_ndarray.py
new file mode 100644
--- /dev/null
+++ b/tests/cupy_tests/test_ndarray.py
@@ -0,0 +1,36 @@
+import unittest
+
+import cupy
+
+
+class TestGetSize(unittest.TestCase):
+
+    def test_none(self):
+        self.assertEqual(cupy._get_size(None), ())
+
+    def check_collection(self, a):
+        self.assertEqual(cupy._get_size(a), tuple(a))
+
+    def test_list(self):
+        self.check_collection([1, 2, 3])
+
+    def test_tuple(self):
+        self.check_collection((1, 2, 3))
+
+    def test_int(self):
+        self.assertEqual(cupy._get_size(1), (1,))
+
+    def test_float(self):
+        with self.assertRaises(ValueError):
+            cupy._get_size(1.0)
+
+
+class TestNdarrayInit(unittest.TestCase):
+
+    def test_shape_none(self):
+        a = cupy.ndarray(None)
+        self.assertTupleEqual(a.shape, ())
+
+    def test_shape_int(self):
+        a = cupy.ndarray(3)
+        self.assertTupleEqual(a.shape, (3, ))