internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: dask/dask

Issue:
Add tests to package
In `setup.py`, make sure `tests` subdirectories are included in the package (otherwise, it is not possible for a user with an installed version of dask to verify its integrity).



Discussion:
How would you advise this is done? We rely on pytest as our testing framework, and I'd be hesitant to add that as a dependency. Would just adding the tests to the package be enough, or should we provide a `test` function as in numpy/pandas/etc...?

Adding pytest won't be needed.  Just add `__init__.py` files in all test directories.


Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -14,6 +14,12 @@
 }
 extras_require['complete'] = sorted(set(sum(extras_require.values(), [])))
 
+packages = ['dask', 'dask.array', 'dask.bag', 'dask.store', 'dask.bytes',
+            'dask.dataframe', 'dask.dataframe.tseries', 'dask.diagnostics']
+
+tests = [p + '.tests' for p in packages]
+
+
 setup(name='dask',
       version=dask.__version__,
       description='Minimal task scheduling abstraction',
@@ -22,8 +28,7 @@
       maintainer_email='mrocklin@gmail.com',
       license='BSD',
       keywords='task-scheduling parallelism',
-      packages=['dask', 'dask.array', 'dask.bag', 'dask.store', 'dask.bytes',
-                'dask.dataframe', 'dask.dataframe.tseries', 'dask.diagnostics'],
+      packages=packages + tests,
       long_description=(open('README.rst').read() if exists('README.rst')
                         else ''),
       extras_require=extras_require,


Test patch:
diff --git a/dask/array/tests/__init__.py b/dask/array/tests/__init__.py
new file mode 100644
diff --git a/dask/bag/tests/__init__.py b/dask/bag/tests/__init__.py
new file mode 100644
diff --git a/dask/bytes/tests/__init__.py b/dask/bytes/tests/__init__.py
new file mode 100644
diff --git a/dask/dataframe/tests/__init__.py b/dask/dataframe/tests/__init__.py
new file mode 100644
diff --git a/dask/dataframe/tests/test_multi.py b/dask/dataframe/tests/test_multi.py
--- a/dask/dataframe/tests/test_multi.py
+++ b/dask/dataframe/tests/test_multi.py
@@ -5,9 +5,9 @@
         hash_join, concat_indexed_dataframes)
 import pandas.util.testing as tm
 from dask.async import get_sync
+from dask.dataframe.utils import eq
 
 import pytest
-from test_dataframe import eq
 
 
 def test_align_partitions():
diff --git a/dask/diagnostics/tests/__init__.py b/dask/diagnostics/tests/__init__.py
new file mode 100644
diff --git a/dask/store/tests/__init__.py b/dask/store/tests/__init__.py
new file mode 100644
diff --git a/dask/tests/__init__.py b/dask/tests/__init__.py
new file mode 100644
Repository: dask/dask

Issue:
from_pandas should support empty data
Related to #1222. Allow to create empty data via `from_panads`. Currently it raises `ValueError`.

```
dd.from_pandas(pd.DataFrame(), 1)
# ValueError: range() arg 3 must not be zero
```



Discussion:

Resolving patch:
diff --git a/dask/dataframe/io.py b/dask/dataframe/io.py
--- a/dask/dataframe/io.py
+++ b/dask/dataframe/io.py
@@ -158,16 +158,20 @@ def from_pandas(data, npartitions=None, chunksize=None, sort=True, name=None):
     else:
         npartitions = int(ceil(nrows / chunksize))
 
+    name = name or ('from_pandas-' + tokenize(data, chunksize))
+
+    if not nrows:
+        return _Frame({(name, 0): data}, name, data, [None, None])
+
     if sort and not data.index.is_monotonic_increasing:
         data = data.sort_index(ascending=True)
     if sort:
         divisions, locations = sorted_division_locations(data.index,
                                                          chunksize=chunksize)
     else:
-        divisions = [None] * (npartitions + 1)
         locations = list(range(0, nrows, chunksize)) + [len(data)]
+        divisions = [None] * len(locations)
 
-    name = name or ('from_pandas-' + tokenize(data, chunksize))
     dsk = dict(((name, i), data.iloc[start: stop])
                for i, (start, stop) in enumerate(zip(locations[:-1],
                    locations[1:])))


Test patch:
diff --git a/dask/dataframe/tests/test_io.py b/dask/dataframe/tests/test_io.py
--- a/dask/dataframe/tests/test_io.py
+++ b/dask/dataframe/tests/test_io.py
@@ -1101,3 +1101,15 @@ def test_read_csv_singleton_dtype():
     with filetext(data, mode='wb') as fn:
         eq(pd.read_csv(fn, dtype=float),
            dd.read_csv(fn, dtype=float))
+
+
+def test_from_pandas_small():
+    for sort in [True, False]:
+        for i in [0, 2]:
+            df = pd.DataFrame({'x': [0] * i})
+            ddf = dd.from_pandas(df, npartitions=5, sort=sort)
+            eq(df, ddf)
+
+            s = pd.Series([0] * i, name='x')
+            ds = dd.from_pandas(s, npartitions=5, sort=sort)
+            eq(s, ds)
Repository: dask/dask

Issue:
Incorrect dtype information
Version 0.10.0

```
import dask.dataframe as dd
dta = dd.from_pandas(pd.DataFrame([['1', '2'], ['3', '4']]), npartitions=2)
dta = dta.assign(y=dta[1].astype(int))
```

```
In [13]: dta.dtypes
Out[13]:
0     object
1     object
y    float64
dtype: object

In [14]: dta.y.compute()
Out[14]:
0    2
1    4
Name: y, dtype: int64
```



Discussion:

Resolving patch:
diff --git a/dask/dataframe/core.py b/dask/dataframe/core.py
--- a/dask/dataframe/core.py
+++ b/dask/dataframe/core.py
@@ -1175,7 +1175,8 @@ def map(self, arg, na_action=None):
 
     @derived_from(pd.Series)
     def astype(self, dtype):
-        return map_partitions(pd.Series.astype, self.name, self, dtype=dtype)
+        return map_partitions(pd.Series.astype, self._pd.astype(dtype),
+                              self, dtype=dtype)
 
     @derived_from(pd.Series)
     def dropna(self):


Test patch:
diff --git a/dask/dataframe/tests/test_dataframe.py b/dask/dataframe/tests/test_dataframe.py
--- a/dask/dataframe/tests/test_dataframe.py
+++ b/dask/dataframe/tests/test_dataframe.py
@@ -1662,3 +1662,13 @@ def test_info(capsys):
                   "Data columns (total 2 columns):\n"
                   "long_column_name    int64\n"
                   "short_name          int64\n")
+
+
+def test_gh_1301():
+    df = pd.DataFrame([['1', '2'], ['3', '4']])
+    ddf = dd.from_pandas(df, npartitions=2)
+    ddf2 = ddf.assign(y=ddf[1].astype(int))
+    eq(ddf2,
+       df.assign(y=df[1].astype(int)))
+
+    assert ddf2.dtypes['y'] == np.dtype(int)
Repository: dask/dask

Issue:
Add documentation and example for dask.array.histogram
After reading http://stackoverflow.com/questions/38086741/how-to-draw-a-histogram-in-dask I realized we are missing good documentation for `dask.array.histogram`.

http://dask.pydata.org/en/latest/array-api.html#dask.array.histogram:

> dask.array.histogram(a, bins=None, range=None, normed=False, weights=None, density=None)

If `bins` and `range` are required we should specify so.

The example can be taken from @mrocklin answer or pick a simpler/less random one.



Discussion:
+1


Resolving patch:
diff --git a/dask/array/core.py b/dask/array/core.py
--- a/dask/array/core.py
+++ b/dask/array/core.py
@@ -2668,15 +2668,36 @@ def histogram(a, bins=None, range=None, normed=False, weights=None, density=None
     Follows the signature of numpy.histogram exactly with the following
     exceptions:
 
-    - either the ``bins`` or ``range`` argument is required as computing
-      ``min`` and ``max`` over blocked arrays is an expensive operation
-      that must be performed explicitly.
+    - Either an iterable specifying the ``bins`` or the number of ``bins``
+      and a ``range`` argument is required as computing ``min`` and ``max``
+      over blocked arrays is an expensive operation that must be performed
+      explicitly.
 
     - ``weights`` must be a dask.array.Array with the same block structure
-       as ``a``.
+      as ``a``.
 
-    Original signature follows below.
-    """ + np.histogram.__doc__
+    Examples
+    --------
+    Using number of bins and range:
+
+    >>> import dask.array as da
+    >>> import numpy as np
+    >>> x = da.from_array(np.arange(10000), chunks=10)
+    >>> h, bins = da.histogram(x, bins=10, range=[0, 10000])
+    >>> bins
+    array([     0.,   1000.,   2000.,   3000.,   4000.,   5000.,   6000.,
+             7000.,   8000.,   9000.,  10000.])
+    >>> h.compute()
+    array([1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000])
+
+    Explicitly specifying the bins:
+
+    >>> h, bins = da.histogram(x, bins=np.array([0, 5000, 10000]))
+    >>> bins
+    array([    0,  5000, 10000])
+    >>> h.compute()
+    array([5000, 5000])
+    """
     if bins is None or (range is None and bins is None):
         raise ValueError('dask.array.histogram requires either bins '
                          'or bins and range to be defined.')


Test patch:
Repository: dask/dask

Issue:
where's da.absolute?



Discussion:

Resolving patch:
diff --git a/dask/array/__init__.py b/dask/array/__init__.py
--- a/dask/array/__init__.py
+++ b/dask/array/__init__.py
@@ -13,8 +13,8 @@
         logical_and, logical_or, logical_xor, logical_not, maximum, minimum,
         fmax, fmin, isreal, iscomplex, isfinite, isinf, isnan, signbit,
         copysign, nextafter, ldexp, fmod, floor, ceil, trunc, degrees, radians,
-        rint, fix, angle, real, imag, clip, fabs, sign, frexp, modf, around,
-        isnull, notnull, isclose, eye, triu, tril, diag, corrcoef)
+        rint, fix, angle, real, imag, clip, fabs, sign, absolute, frexp, modf,
+        around, isnull, notnull, isclose, eye, triu, tril, diag, corrcoef)
 from .reductions import (sum, prod, mean, std, var, any, all, min, max, vnorm,
                          moment,
                          argmin, argmax,
diff --git a/dask/array/core.py b/dask/array/core.py
--- a/dask/array/core.py
+++ b/dask/array/core.py
@@ -2307,6 +2307,7 @@ def wrap_elemwise(func, **kwargs):
 clip = wrap_elemwise(np.clip)
 fabs = wrap_elemwise(np.fabs)
 sign = wrap_elemwise(np.sign)
+absolute = wrap_elemwise(np.absolute)
 
 
 def frexp(x):


Test patch:
diff --git a/dask/array/tests/test_array_core.py b/dask/array/tests/test_array_core.py
--- a/dask/array/tests/test_array_core.py
+++ b/dask/array/tests/test_array_core.py
@@ -1201,6 +1201,8 @@ def test_arithmetic():
     assert_eq(da.clip(b, 1, 4), np.clip(y, 1, 4))
     assert_eq(da.fabs(b), np.fabs(y))
     assert_eq(da.sign(b - 2), np.sign(y - 2))
+    assert_eq(da.absolute(b - 2), np.absolute(y - 2))
+    assert_eq(da.absolute(b - 2 + 1j), np.absolute(y - 2 + 1j))
 
     l1, l2 = da.frexp(a)
     r1, r2 = np.frexp(x)
Repository: dask/dask

Issue:
is there a changelog?
Is there a changelog?

If there is not there's no way to know what have changed since last update which is... disappointing!



Discussion:
Major change notes go out in release e-mails on blaze-dev.  I agree with you that a single changelog would be nice.  

Rather than be disappointed I recommend that you contribute and help to make this open source project better.  Perhaps start writing up backlogs of release notes based on PR descriptions?  I suspect that once momentum around a changelog is started that it will continue.

Yes I agree with you. I'm not complaining.

I'm still getting the grasp of how to do basic things.

I have just noticed that an upgrade was made in the last 24h and was curious to know what changed.
I hope to be able to contribute soon.

: )

Thanks!

Adding backlogs for the releases would be a huge help and probably pretty informative.  I think the best way to do this would be to search through the [blaze-dev archives](https://groups.google.com/a/continuum.io/forum/#!forum/blaze-dev) for all [dask release](https://groups.google.com/a/continuum.io/forum/#!topicsearchin/blaze-dev/release) e-mails, copying down the notes there, and adding them to a new release document in this repository.

I'll send out an e-mail with notes for the recent version after binaries get uploaded to conda-forge.  There is a bit of a delay between uploading to PyPI and uploading to conda-forge

One thing that really helps is to update the changelog with every PR. You still need to give it a review when you make a release to ensure it has the appropriate emphasis, but it makes the process much easier.

There's certainly little more frustrating than being blocked on making a release (e.g., with important bug fixes) because you haven't updated the docs yet. This helps avoid that situation.


Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -26,7 +26,7 @@
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.mathjax',
-              'sphinx.ext.autosummary', 'numpydoc']
+              'sphinx.ext.autosummary', 'sphinx.ext.extlinks', 'numpydoc']
 
 numpydoc_show_class_members = False
 
@@ -293,3 +293,8 @@
 
 # Allow duplicate toc entries.
 #epub_tocdup = True
+
+extlinks = {
+    'issue': ('https://github.com/dask/dask/issues/%s', 'GH#'),
+    'pr': ('https://github.com/dask/dask/pull/%s', 'GH#')
+}
\ No newline at end of file


Test patch:
Repository: dask/dask

Issue:
Dask.dataframe.resample triggers FutureWarnings
I think we're still using the old Pandas API internally



Discussion:
Shouldn't be. Do you have a reproducible example?

``` python
In [1]: import dask.dataframe as dd

In [2]: df = dd.demo.make_timeseries('2015', '2016',
   ...:                              {'value': float, 'name': str, 'id': int},
   ...:                              freq='10s', partition_freq='7d', seed=1)
   ...: 
   ...: 

In [3]: df.value.resample('1d').mean().compute()
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/dask-0.11.0-py3.5.egg/dask/dataframe/tseries/resample.py:85: FutureWarning: pandas.core.datetools.to_offset is deprecated. Please use pandas.tseries.frequencies.to_offset instead.
  rule = pd.datetools.to_offset(rule)
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/dask-0.11.0-py3.5.egg/dask/dataframe/tseries/resample.py:86: FutureWarning: pandas.core.datetools.Day is deprecated. Please use pandas.tseries.offsets.Day instead.
  day_nanos = pd.datetools.Day().nanos
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/dask-0.11.0-py3.5.egg/dask/dataframe/tseries/resample.py:39: FutureWarning: pandas.core.datetools.to_offset is deprecated. Please use pandas.tseries.frequencies.to_offset instead.
  rule = pd.datetools.to_offset(rule)
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/dask-0.11.0-py3.5.egg/dask/dataframe/tseries/resample.py:44: FutureWarning: how in .resample() is deprecated
the new syntax is .resample(...).count()
  temp = divs.resample(rule, how='count', closed=closed, label='left')
```

Found it. Fixed.


Resolving patch:
diff --git a/dask/dataframe/tseries/resample.py b/dask/dataframe/tseries/resample.py
--- a/dask/dataframe/tseries/resample.py
+++ b/dask/dataframe/tseries/resample.py
@@ -41,7 +41,7 @@ def _resample_bin_and_out_divs(divisions, rule, closed='left', label='left'):
 
     # Determine bins to apply `how` to. Disregard labeling scheme.
     divs = pd.Series(range(len(divisions)), index=divisions)
-    temp = divs.resample(rule, how='count', closed=closed, label='left')
+    temp = divs.resample(rule, closed=closed, label='left').count()
     tempdivs = temp.loc[temp > 0].index
 
     # Cleanup closed == 'right' and label == 'right'


Test patch:
Repository: dask/dask

Issue:
"Natural" assignment to column is ignored
Below, the individual column object (a Series?) is modified, but the enclosing Dask dataframe doesn't notice:

```
>>> df = pd.DataFrame({'x': [1, 2, 3, 4, 5],
...:                   'y': [1., 2., 3., 4., 5.]})
...:                   
>>> ddf = dd.from_pandas(df, npartitions=2)
>>> ddf.x
dd.Series<getitem..., npartitions=2, divisions=(0, 3, 4)>
>>> ddf.x.compute()

0    1
1    2
2    3
3    4
4    5
Name: x, dtype: int64
>>> ddf.x **= 0.5
>>> ddf.x.compute()

0    1.000000
1    1.414214
2    1.732051
3    2.000000
4    2.236068
Name: x, dtype: float64
>>> ddf.compute()

   x    y
0  1  1.0
1  2  2.0
2  3  3.0
3  4  4.0
4  5  5.0
```

Compare with pandas:

```
>>> df

   x    y
0  1  1.0
1  2  2.0
2  3  3.0
3  4  4.0
4  5  5.0
>>> df.x **= 0.5
>>> df

          x    y
0  1.000000  1.0
1  1.414214  2.0
2  1.732051  3.0
3  2.000000  4.0
4  2.236068  5.0
```



Discussion:
`assign()` does the trick:

```
>>> res = ddf.assign(x=ddf.x ** 0.5)
>>> res.compute()

          x    y
0  1.000000  1.0
1  1.189207  2.0
2  1.316074  3.0
3  1.414214  4.0
4  1.495349  5.0
```

Thanks for the bug report. We don't support mutation, and should probably error informatively in these cases.


Resolving patch:
diff --git a/dask/dataframe/core.py b/dask/dataframe/core.py
--- a/dask/dataframe/core.py
+++ b/dask/dataframe/core.py
@@ -1930,6 +1930,17 @@ def __setitem__(self, key, value):
         self._name = df._name
         self._meta = df._meta
 
+    def __setattr__(self, key, value):
+        try:
+            columns = object.__getattribute__(self, '_meta').columns
+        except AttributeError:
+            columns = ()
+
+        if key in columns:
+            self[key] = value
+        else:
+            object.__setattr__(self, key, value)
+
     def __getattr__(self, key):
         if key in self.columns:
             meta = self._meta[key]


Test patch:
diff --git a/dask/dataframe/tests/test_dataframe.py b/dask/dataframe/tests/test_dataframe.py
--- a/dask/dataframe/tests/test_dataframe.py
+++ b/dask/dataframe/tests/test_dataframe.py
@@ -2003,6 +2003,26 @@ def test_columns_assignment():
     eq(df, ddf)
 
 
+def test_attribute_assignment():
+    df = pd.DataFrame({'x': [1, 2, 3, 4, 5],
+                       'y': [1., 2., 3., 4., 5.]})
+    ddf = dd.from_pandas(df, npartitions=2)
+
+    ddf.y = ddf.x + ddf.y
+    eq(ddf, df.assign(y=df.x + df.y))
+
+
+def test_inplace_operators():
+    df = pd.DataFrame({'x': [1, 2, 3, 4, 5],
+                       'y': [1., 2., 3., 4., 5.]})
+    ddf = dd.from_pandas(df, npartitions=2)
+
+    ddf.y **= 0.5
+
+    eq(ddf.y, df.y ** 0.5)
+    eq(ddf, df.assign(y=df.y ** 0.5))
+
+
 @pytest.mark.parametrize("skipna", [True, False])
 @pytest.mark.parametrize("idx", [
     np.arange(100),
Repository: dask/dask

Issue:
warning directly after dask import
After importing dask, I sometimes get the following warning:

[path_to_anaconda]/python2.7/site-packages/psutil/_pslinux.py:338: RuntimeWarning: shared memory stats couldn't be determined and was set to 0
warnings.warn(msg, RuntimeWarning)

Details about the used system:
Dask: 0.10.2
Python version: 2.7.12 |Anaconda custom (64-bit)| (default, Jul 2 2016, 17:42:40)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
Platform: Linux-2.6.27.19-5-default-x86_64-with-SuSE-11-x86_64
Byte-ordering: little
Detected cores: 40
Default encoding: ascii
Default FS encoding: UTF-8



Discussion:

Resolving patch:
diff --git a/dask/dataframe/csv.py b/dask/dataframe/csv.py
--- a/dask/dataframe/csv.py
+++ b/dask/dataframe/csv.py
@@ -1,7 +1,7 @@
 from __future__ import print_function, division, absolute_import
 
 from io import BytesIO
-from warnings import warn
+from warnings import warn, catch_warnings, simplefilter
 
 try:
     import psutil
@@ -128,9 +128,11 @@ def auto_blocksize(total_memory, cpu_count):
 
 # guess blocksize if psutil is installed or use acceptable default one if not
 if psutil is not None:
-    TOTAL_MEM = psutil.virtual_memory().total
-    CPU_COUNT = psutil.cpu_count()
-    AUTO_BLOCKSIZE = auto_blocksize(TOTAL_MEM, CPU_COUNT)
+    with catch_warnings():
+        simplefilter("ignore", RuntimeWarning)
+        TOTAL_MEM = psutil.virtual_memory().total
+        CPU_COUNT = psutil.cpu_count()
+        AUTO_BLOCKSIZE = auto_blocksize(TOTAL_MEM, CPU_COUNT)
 else:
     AUTO_BLOCKSIZE = 2**25
 


Test patch:
Repository: dask/dask

Issue:
boolean slicing was very slow to error
Using the pydata DC notebook this was very slow to error.

```
x = da.random.normal(loc=10,scale=0.1,size=[20000,20000],chunks=[1000,1000])
y = x[x>10]
```



Discussion:
Thanks for the bug report. Boolean slicing isn't implemented, and can't be under the current design since we don't know the size of the output (it depends on the values of x, not the shape/dtype). What's happening here is that we're accidentally calling compute here when we should just error immediately. Fixing now.


Resolving patch:
diff --git a/dask/array/core.py b/dask/array/core.py
--- a/dask/array/core.py
+++ b/dask/array/core.py
@@ -1097,6 +1097,9 @@ def __getitem__(self, index):
         if not isinstance(index, tuple):
             index = (index,)
 
+        if any(isinstance(i, Array) for i in index):
+            raise NotImplementedError("Indexing with a dask Array")
+
         if all(isinstance(i, slice) and i == slice(None) for i in index):
             return self
 


Test patch:
diff --git a/dask/array/tests/test_slicing.py b/dask/array/tests/test_slicing.py
--- a/dask/array/tests/test_slicing.py
+++ b/dask/array/tests/test_slicing.py
@@ -496,3 +496,12 @@ def test_oob_check():
         x[[6]]
     with pytest.raises(IndexError):
         x[0, 0]
+
+
+def test_index_with_dask_array_errors():
+    x = da.ones((5, 5), chunks=2)
+    with pytest.raises(NotImplementedError):
+        x[x > 10]
+
+    with pytest.raises(NotImplementedError):
+        x[0, x > 10]
Repository: dask/dask

Issue:
DataFrame.__getitem__ on multilevel columns fails
Test case:

``` python
def test_getitem_multilevel():
    pdf = pd.DataFrame({('A', '0') : [1,2,2]})
    ddf = dd.from_pandas(pdf, npartitions=3)

    assert_eq(pdf['A', '0'], ddf['A', '0'])

# result:
# E       NotImplementedError: ('A', '0')
```



Discussion:

Resolving patch:
diff --git a/dask/dataframe/core.py b/dask/dataframe/core.py
--- a/dask/dataframe/core.py
+++ b/dask/dataframe/core.py
@@ -1929,7 +1929,7 @@ def columns(self, columns):
 
     def __getitem__(self, key):
         name = 'getitem-%s' % tokenize(self, key)
-        if np.isscalar(key):
+        if np.isscalar(key) or isinstance(key, tuple):
 
             if isinstance(self._meta.index, (pd.DatetimeIndex, pd.PeriodIndex)):
                 if key not in self._meta.columns:


Test patch:
diff --git a/dask/dataframe/tests/test_dataframe.py b/dask/dataframe/tests/test_dataframe.py
--- a/dask/dataframe/tests/test_dataframe.py
+++ b/dask/dataframe/tests/test_dataframe.py
@@ -2430,6 +2430,14 @@ def test_getitem_meta():
     assert_eq(df.col2[df.col1 == 'a'], ddf.col2[ddf.col1 == 'a'])
 
 
+def test_getitem_multilevel():
+    pdf = pd.DataFrame({('A', '0') : [1,2,2], ('B', '1') : [1,2,3]})
+    ddf = dd.from_pandas(pdf, npartitions=3)
+
+    assert_eq(pdf['A', '0'], ddf['A', '0'])
+    assert_eq(pdf[[('A', '0'), ('B', '1')]], ddf[[('A', '0'), ('B', '1')]])
+
+
 def test_set_index_sorted_min_max_same():
     a = pd.DataFrame({'x': [1, 2, 3], 'y': [0, 0, 0]})
     b = pd.DataFrame({'x': [1, 2, 3], 'y': [1, 1, 1]})