Repository: dask/dask

Issue:
apply_gufunc input validation fails to raise exception on extra args
**What happened**:
There is a missing raise in [apply_gufunc](https://github.com/dask/dask/blob/1a6a85258bccb14fe37bb54c211beeeffd46cd55/dask/array/gufunc.py#L343)
**What you expected to happen**:
ValueError to be raised.
This is later somehow fixed in a way I don't understand in transpose_args

**Minimal Complete Verifiable Example**:

```python
    def add(x, y):
        return x + y

    a = da.from_array(np.array([1, 2, 3]), chunks=2, name="a")
    b = da.from_array(np.array([1, 2, 3]), chunks=2, name="b") 
    # this should raise an error
    z = apply_gufunc(add, "(),()->()", a, b, 0, output_dtypes=a.dtype)
```

**Anything else we need to know?**:
This was found using [lgtm](https://lgtm.com/projects/g/dask/dask/alerts/?mode=tree&ruleFocus=1505923886371)
PR and added test on the way.

**Environment**:

- Dask version: 2021.05.1
- Python version:  3.8.10
- Operating System: linux
- Install method (conda, pip, source): conda


Discussion:

Patch:
diff --git a/dask/array/gufunc.py b/dask/array/gufunc.py
index b26297c27..f94133262 100644
--- a/dask/array/gufunc.py
+++ b/dask/array/gufunc.py
@@ -340,7 +340,7 @@ def apply_gufunc(func, signature, *args, **kwargs):
     args = [asarray(a) for a in args]
 
     if len(input_coredimss) != len(args):
-        ValueError(
+        raise ValueError(
             "According to `signature`, `func` requires %d arguments, but %s given"
             % (len(input_coredimss), len(args))
         )
diff --git a/dask/dataframe/core.py b/dask/dataframe/core.py
index f08ebdd90..81ff1bddf 100644
--- a/dask/dataframe/core.py
+++ b/dask/dataframe/core.py
@@ -65,6 +65,7 @@ from .optimize import optimize
 from .utils import (
     PANDAS_GT_100,
     PANDAS_GT_110,
+    PANDAS_GT_120,
     check_matching_columns,
     clear_known_categories,
     drop_by_shallow_copy,
@@ -3880,6 +3881,14 @@ class DataFrame(_Frame):
 
             if isinstance(self._meta.index, (pd.DatetimeIndex, pd.PeriodIndex)):
                 if key not in self._meta.columns:
+                    if PANDAS_GT_120:
+                        warnings.warn(
+                            "Indexing a DataFrame with a datetimelike index using a single "
+                            "string to slice the rows, like `frame[string]`, is deprecated "
+                            "and will be removed in a future version. Use `frame.loc[string]` "
+                            "instead.",
+                            FutureWarning,
+                        )
                     return self.loc[key]
 
             # error is raised from pandas
diff --git a/dask/sizeof.py b/dask/sizeof.py
index fb8d43d78..570b62513 100644
--- a/dask/sizeof.py
+++ b/dask/sizeof.py
@@ -1,3 +1,4 @@
+import itertools
 import random
 import sys
 from array import array
@@ -44,12 +45,16 @@ def sizeof_array(o):
 @sizeof.register(frozenset)
 def sizeof_python_collection(seq):
     num_items = len(seq)
-    samples = 10
-    if num_items > samples:
-        s = getsizeof(seq) + num_items / samples * sum(
-            map(sizeof, random.sample(seq, samples))
-        )
-        return int(s)
+    num_samples = 10
+    if num_items > num_samples:
+        if isinstance(seq, (set, frozenset)):
+            # As of Python v3.9, it is deprecated to call random.sample() on
+            # sets but since sets are unordered anyways we can simply pick
+            # the first `num_samples` items.
+            samples = itertools.islice(seq, num_samples)
+        else:
+            samples = random.sample(seq, num_samples)
+        return getsizeof(seq) + int(num_items / num_samples * sum(map(sizeof, samples)))
     else:
         return getsizeof(seq) + sum(map(sizeof, seq))
 
diff --git a/docs/source/diagnostics-distributed.rst b/docs/source/diagnostics-distributed.rst
index 5dd88bab4..d3f02d646 100644
--- a/docs/source/diagnostics-distributed.rst
+++ b/docs/source/diagnostics-distributed.rst
@@ -33,7 +33,8 @@ For local use this happens when you create a client with no arguments:
 It is typically served at ``http://localhost:8787/status`` ,
 but may be served elsewhere if this port is taken.
 The address of the dashboard will be displayed if you are in a Jupyter Notebook,
-or can be queried from ``client.scheduler_info()['services']``.
+or can be queried from ``client.dashboard_link``
+(or for older versions of distributed, ``client.scheduler_info()['services']``).
 
 There are numerous pages with information about task runtimes, communication,
 statistical profiling, load balancing, memory use, and much more.
diff --git a/docs/source/support.rst b/docs/source/support.rst
index d25bee18a..ec99d583f 100644
--- a/docs/source/support.rst
+++ b/docs/source/support.rst
@@ -33,7 +33,7 @@ Conversation happens in the following places:
 
     You can subscribe to this calendar to be notified of changes:
 
-    * `Google Calendar <https://calendar.google.com/calendar/embed?src=4l0vts0c1cgdbq5jhcogj55sfs%40group.calendar.google.com>`__
+    * `Google Calendar <https://calendar.google.com/calendar/u/0?cid=NGwwdnRzMGMxY2dkYnE1amhjb2dqNTVzZnNAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ>`__
     * `iCal <https://calendar.google.com/calendar/ical/4l0vts0c1cgdbq5jhcogj55sfs%40group.calendar.google.com/public/basic.ics>`__
 
 .. _`Stack Overflow with the #dask tag`: https://stackoverflow.com/questions/tagged/dask
diff --git a/setup.cfg b/setup.cfg
index b5f912f91..57150f1b0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -41,7 +41,7 @@ test = pytest
 markers:
   network: Test requires an internet connection
   slow: Skipped unless --runslow passed
-addopts = -v -rsx --durations=10
+addopts = -v -rsxfE --durations=10
 filterwarnings =
     # From Cython-1753
     ignore:can't resolve:ImportWarning


Test patch:
diff --git a/dask/array/tests/test_gufunc.py b/dask/array/tests/test_gufunc.py
old mode 100755
new mode 100644
index ce4951b56..982bd7fa6
--- a/dask/array/tests/test_gufunc.py
+++ b/dask/array/tests/test_gufunc.py
@@ -56,6 +56,16 @@ def test_apply_gufunc_axes_input_validation_01():
         apply_gufunc(foo, "(i)->()", a, axes=[0, 0])
 
 
+def test_apply_gufunc_axes_args_validation():
+    def add(x, y):
+        return x + y
+
+    a = da.from_array(np.array([1, 2, 3]), chunks=2, name="a")
+    b = da.from_array(np.array([1, 2, 3]), chunks=2, name="b")
+    with pytest.raises(ValueError):
+        apply_gufunc(add, "(),()->()", a, b, 0, output_dtypes=a.dtype)
+
+
 def test__validate_normalize_axes_01():
     with pytest.raises(ValueError):
         _validate_normalize_axes([(1, 0)], None, False, [("i", "j")], ("j",))
diff --git a/dask/dataframe/tests/test_indexing.py b/dask/dataframe/tests/test_indexing.py
index 31f26edf8..9e2cb666a 100644
--- a/dask/dataframe/tests/test_indexing.py
+++ b/dask/dataframe/tests/test_indexing.py
@@ -429,10 +429,13 @@ def test_getitem_timestamp_str():
     )
     ddf = dd.from_pandas(df, 10)
 
-    # partial string slice
-    # TODO(pandas) starting with pandas 1.2, __getitem__ with an implicit slice
-    # is deprecated -> should we deprecate this in dask as well?
-    assert_eq(df.loc["2011-01-02"], ddf["2011-01-02"])
+    if PANDAS_GT_120:
+        with pytest.warns(
+            FutureWarning, match="Indexing a DataFrame with a datetimelike"
+        ):
+            assert_eq(df.loc["2011-01-02"], ddf["2011-01-02"])
+    else:
+        assert_eq(df.loc["2011-01-02"], ddf["2011-01-02"])
     assert_eq(df["2011-01-02":"2011-01-10"], ddf["2011-01-02":"2011-01-10"])
 
     df = pd.DataFrame(
@@ -440,8 +443,8 @@ def test_getitem_timestamp_str():
         index=pd.date_range("2011-01-01", freq="D", periods=100),
     )
     ddf = dd.from_pandas(df, 50)
-    assert_eq(df.loc["2011-01"], ddf["2011-01"])
-    assert_eq(df.loc["2011"], ddf["2011"])
+    assert_eq(df.loc["2011-01"], ddf.loc["2011-01"])
+    assert_eq(df.loc["2011"], ddf.loc["2011"])
 
     assert_eq(df["2011-01":"2012-05"], ddf["2011-01":"2012-05"])
     assert_eq(df["2011":"2015"], ddf["2011":"2015"])
@@ -486,9 +489,12 @@ def test_getitem_period_str():
     ddf = dd.from_pandas(df, 10)
 
     # partial string slice
-    # TODO(pandas) starting with pandas 1.2, __getitem__ with an implicit slice
-    # is deprecated -> should we deprecate this in dask as well?
-    if not PANDAS_GT_120:
+    if PANDAS_GT_120:
+        with pytest.warns(
+            FutureWarning, match="Indexing a DataFrame with a datetimelike"
+        ):
+            assert_eq(df.loc["2011-01-02"], ddf["2011-01-02"])
+    else:
         assert_eq(df["2011-01-02"], ddf["2011-01-02"])
     assert_eq(df["2011-01-02":"2011-01-10"], ddf["2011-01-02":"2011-01-10"])
     # same reso, dask result is always DataFrame
@@ -498,8 +504,21 @@ def test_getitem_period_str():
         index=pd.period_range("2011-01-01", freq="D", periods=100),
     )
     ddf = dd.from_pandas(df, 50)
-    if not PANDAS_GT_120:
+
+    if PANDAS_GT_120:
+        with pytest.warns(
+            FutureWarning, match="Indexing a DataFrame with a datetimelike"
+        ):
+            assert_eq(df.loc["2011-01"], ddf["2011-01"])
+    else:
         assert_eq(df["2011-01"], ddf["2011-01"])
+
+    if PANDAS_GT_120:
+        with pytest.warns(
+            FutureWarning, match="Indexing a DataFrame with a datetimelike"
+        ):
+            assert_eq(df.loc["2011"], ddf["2011"])
+    else:
         assert_eq(df["2011"], ddf["2011"])
 
     assert_eq(df["2011-01":"2012-05"], ddf["2011-01":"2012-05"])