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.
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)

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
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)

pip install -e .[testing,functions,server,tests]
parse_log_pytest
pytest
pytest pytest-cov pytest-attrib mock requests-mock requests
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
beautifulsoup4==4.12.3
certifi==2021.5.30
charset-normalizer==2.0.12
coards==1.0.5
coverage==6.2
docopt==0.6.2
flake8==5.0.4
gsw==3.4.0
gunicorn==21.2.0
idna==3.10
importlib-metadata==4.2.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
Jinja2==3.0.3
lxml==5.3.1
MarkupSafe==2.0.1
mccabe==0.7.0
MechanicalSoup==1.3.0
mock==5.2.0
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
nose==1.3.7
numpy==1.19.5
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycodestyle==2.9.1
-e git+https://github.com/pydap/pydap.git@019d60b0faee4ec8ce2b7da6f64aac8ac0b53c28#egg=Pydap
pyflakes==2.5.0
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
pytest-attrib==0.1.3
pytest-cov==4.0.0
requests==2.27.1
requests-mock==1.12.1
scipy==1.5.4
singledispatch==3.7.0
six==1.17.0
soupsieve==2.3.2.post1
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
tomli==1.2.3
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
urllib3==1.26.20
waitress==2.0.0
WebOb==1.8.9
WebTest==3.0.0
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: pydap
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - beautifulsoup4==4.12.3
      - charset-normalizer==2.0.12
      - coards==1.0.5
      - coverage==6.2
      - docopt==0.6.2
      - flake8==5.0.4
      - gsw==3.4.0
      - gunicorn==21.2.0
      - idna==3.10
      - importlib-metadata==4.2.0
      - jinja2==3.0.3
      - lxml==5.3.1
      - markupsafe==2.0.1
      - mccabe==0.7.0
      - mechanicalsoup==1.3.0
      - mock==5.2.0
      - nose==1.3.7
      - numpy==1.19.5
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pytest-attrib==0.1.3
      - pytest-cov==4.0.0
      - requests==2.27.1
      - requests-mock==1.12.1
      - scipy==1.5.4
      - singledispatch==3.7.0
      - six==1.17.0
      - soupsieve==2.3.2.post1
      - tomli==1.2.3
      - urllib3==1.26.20
      - waitress==2.0.0
      - webob==1.8.9
      - webtest==3.0.0
prefix: /opt/conda/envs/pydap

src/pydap/tests/test_handlers_dap.py::TestArrayStringBaseType::test_getitem
src/pydap/tests/test_handlers_dap.py::TestDapHandler::test_base_type_with_projection src/pydap/tests/test_handlers_dap.py::TestDapHandler::test_grid src/pydap/tests/test_handlers_dap.py::TestDapHandler::test_grid_array_with_projection src/pydap/tests/test_handlers_dap.py::TestDapHandler::test_grid_map_with_projection src/pydap/tests/test_handlers_dap.py::TestDapHandler::test_grid_with_projection src/pydap/tests/test_handlers_dap.py::TestDapHandler::test_sequence src/pydap/tests/test_handlers_dap.py::TestDapHandler::test_sequence_with_projection src/pydap/tests/test_handlers_dap.py::TestBaseProxy::test_comparisons src/pydap/tests/test_handlers_dap.py::TestBaseProxy::test_getitem src/pydap/tests/test_handlers_dap.py::TestBaseProxy::test_getitem_out_of_bound src/pydap/tests/test_handlers_dap.py::TestBaseProxy::test_inexact_division src/pydap/tests/test_handlers_dap.py::TestBaseProxy::test_iteration src/pydap/tests/test_handlers_dap.py::TestBaseProxy::test_len src/pydap/tests/test_handlers_dap.py::TestBaseProxy::test_repr src/pydap/tests/test_handlers_dap.py::TestBaseProxyShort::test_getitem src/pydap/tests/test_handlers_dap.py::TestBaseProxyString::test_getitem src/pydap/tests/test_handlers_dap.py::TestSequenceProxy::test_attributes src/pydap/tests/test_handlers_dap.py::TestSequenceProxy::test_comparisons src/pydap/tests/test_handlers_dap.py::TestSequenceProxy::test_getitem src/pydap/tests/test_handlers_dap.py::TestSequenceProxy::test_iter src/pydap/tests/test_handlers_dap.py::TestSequenceProxy::test_iter_child src/pydap/tests/test_handlers_dap.py::TestSequenceProxy::test_repr src/pydap/tests/test_handlers_dap.py::TestSequenceProxy::test_url src/pydap/tests/test_handlers_dap.py::TestSequenceWithString::test_filtering src/pydap/tests/test_handlers_dap.py::TestSequenceWithString::test_iter src/pydap/tests/test_handlers_dap.py::TestSequenceWithString::test_iter_child src/pydap/tests/test_handlers_dap.py::TestSequenceWithString::test_projection src/pydap/tests/test_handlers_dap.py::TestStringBaseType::test_getitem
src/pydap/handlers/dap.py
src/pydap/handlers/dap.py