Repository: pydap/pydap

Issue:
Unexpected 'flattening' of the array when slicing on BaseProxy
Hello,

I notice the following (unexpected) behavior when using pydap to accessing n-dimensional variable:

```
In [1]: import pydap.client

In [2]: ds = pydap.client.open_url('http://test.opendap.org/opendap/hyrax/data/nc/123.nc')

In [3]: ds
Out[3]: <DatasetType with children 'bears', 'order', 'shot', 'aloan', 'cross', 'i', 'j', 'l'>

In [4]: ds.bears
Out[4]: <GridType with array 'bears' and maps 'i', 'j'>

In [5]: ds.bears.array
Out[5]: <BaseType with data BaseProxy('http://test.opendap.org/opendap/hyrax/data/nc/123.nc', 'bears.bears', dtype('S128'), (2, 3), (slice(None, None, None), slice(None, None, None)))>

In [6]: ds.bears.array.shape
Out[6]: (2, 3)

## slicing the array flattens the output array
In [7]: ds.bears.array[:]
Out[7]:
array([u'ind', u'ist', u'ing', u'uis', u'hab', u'le'],
      dtype='<U3')

In [8]: ds.bears.array[:].shape
Out[8]: (6,)

## And this won't work?
In [9]: np.asarray(ds.bears.array)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-5da01e73285e> in <module>()
----> 1 np.asarray(ds.bears.array)

/Users/daniel.lee/anaconda/envs/pydap/lib/python2.7/site-packages/numpy/core/numeric.pyc in asarray(a, dtype, order)
    480
    481     """
--> 482     return array(a, dtype, copy=False, order=order)
    483
    484 def asanyarray(a, dtype=None, order=None):

ValueError: cannot copy sequence with size 2 to array axis with dimension 6
```

From my best attempt to read over the pydap code, I find [this line](
https://github.com/pydap/pydap/blob/master/src/pydap/handlers/dap.py#L155) suspicious:

```
return np.array([ text_type(x.decode('ascii')) for x in out ], 'S')
```

Namely, I think it's missing a `.reshape(shape)` call at the end.

```
return np.array([ text_type(x.decode('ascii')) for x in out ], 'S').reshape(shape)
```

Is what I'm suggesting here reasonable?

Discovered while investigating pydata/xarray#1174

Discussion:
taeold: Thank you!
jameshiebert: Thanks for this @laliberte ! Looks like my attempt to merge the conflicts via GH's was a bad move (failed the flake8 checks). Do you mind doing a rebase/force-push on this, and then we can merge it in short order.

Patch:
diff --git a/src/pydap/handlers/dap.py b/src/pydap/handlers/dap.py
index e787b9e..cffd44f 100644
--- a/src/pydap/handlers/dap.py
+++ b/src/pydap/handlers/dap.py
@@ -149,7 +149,7 @@ class BaseProxy(object):
         size = int(np.prod(shape))
 
         if self.dtype == np.byte:
-            return np.fromstring(data[:size], 'B')
+            return np.fromstring(data[:size], 'B').reshape(shape)
         elif self.dtype.char in 'SU':
             out = []
             for word in range(size):
@@ -157,7 +157,8 @@ class BaseProxy(object):
                 data = data[4:]
                 out.append(data[:n])
                 data = data[n + (-n % 4):]
-            return np.array([text_type(x.decode('ascii')) for x in out], 'S')
+            return np.array([text_type(x.decode('ascii'))
+                             for x in out], 'S').reshape(shape)
         else:
             try:
                 return np.fromstring(data, self.dtype).reshape(shape)


Test patch:
diff --git a/src/pydap/tests/test_handlers_dap.py b/src/pydap/tests/test_handlers_dap.py
index 2e19e31..03ea757 100644
--- a/src/pydap/tests/test_handlers_dap.py
+++ b/src/pydap/tests/test_handlers_dap.py
@@ -414,3 +414,22 @@ class TestStringBaseType(unittest.TestCase):
         """Test the ``__getitem__`` method."""
         np.testing.assert_array_equal(self.data[:],
                                       np.array("This is a test", dtype='S'))
+
+
+class TestArrayStringBaseType(unittest.TestCase):
+
+    """Regression test for an array of unicode base type."""
+
+    def setUp(self):
+        """Create a WSGI app with array data"""
+        dataset = DatasetType("test")
+        self.original_data = np.array([["This ", "is "], ["a ", "test"]],
+                                      dtype='<U5')
+        dataset["s"] = BaseType("s", self.original_data)
+        self.app = BaseHandler(dataset)
+
+        self.data = DAPHandler("http://localhost:8001/",  self.app).dataset.s
+
+    def test_getitem(self):
+        """Test the ``__getitem__`` method."""
+        np.testing.assert_array_equal(self.data[:], self.original_data)