Repository: dask/dask

Issue:
Deprecate compute keyword for set_index
This is only relevant if you have a disk based shuffle and I don't really know what the advantage of the keyword would be.

It seems like something that we should clean up

Discussion:
github-actions[bot]: ## Unit Test Results
_See [test report](https://dask.github.io/dask/test_report.html) for an extended history of previous test failures. This is useful for diagnosing flaky tests._

     15 files  ±0       15 suites  ±0   3h 20m 25s :stopwatch: - 9m 31s
 12 893 tests ±0   10 922 :white_check_mark: ±0     932 :zzz: ±0  1 039 :x: ±0 
159 776 runs  ±0  142 155 :white_check_mark: +7  16 582 :zzz:  - 7  1 039 :x: ±0 

For more details on these failures, see [this check](https://github.com/dask/dask/runs/20383696569).

Results for commit 41ccf885. ± Comparison against base commit b934d2db.

[test-results]:data:application/gzip;base64,H4sIAO/dn2UC/1XNSw7CIBSF4a0Yxg7g8nYzhgI3IfZhKIyMe5e2ttXh/11yeBFMfZzJ7cLk9ULmmspZoWZX0jQuDRQWatey3sFYvvd9rt4vSC3AiY/0bGj5SehSv77j9rCY85Qb0ia5jtvnVmv17WNcAJPywG2cKWlgt//1lX7H/TQMqbQggnmPxkjqrYpBd4iis04IjZGbgDSgEpI7St4f8QcLoR8BAAA=


Patch:
diff --git a/dask/base.py b/dask/base.py
index 465339336..bf06debce 100644
--- a/dask/base.py
+++ b/dask/base.py
@@ -14,7 +14,7 @@ import warnings
 from collections import OrderedDict
 from collections.abc import Callable, Hashable, Iterator, Mapping
 from concurrent.futures import Executor
-from contextlib import contextmanager
+from contextlib import contextmanager, suppress
 from contextvars import ContextVar
 from enum import Enum
 from functools import partial
@@ -42,6 +42,26 @@ from dask.utils import (
     shorten_traceback,
 )
 
+_DistributedClient = None
+_get_distributed_client = None
+_DISTRIBUTED_AVAILABLE = None
+
+
+def _distributed_available() -> bool:
+    # Lazy import in get_scheduler can be expensive
+    global _DistributedClient, _get_distributed_client, _DISTRIBUTED_AVAILABLE
+    if _DISTRIBUTED_AVAILABLE is not None:
+        return _DISTRIBUTED_AVAILABLE  # type: ignore[unreachable]
+    try:
+        from distributed import Client as _DistributedClient
+        from distributed.worker import get_client as _get_distributed_client
+
+        _DISTRIBUTED_AVAILABLE = True
+    except ImportError:
+        _DISTRIBUTED_AVAILABLE = False
+    return _DISTRIBUTED_AVAILABLE
+
+
 __all__ = (
     "DaskMethodsMixin",
     "annotate",
@@ -1450,13 +1470,12 @@ def get_scheduler(get=None, scheduler=None, collections=None, cls=None):
         elif isinstance(scheduler, str):
             scheduler = scheduler.lower()
 
-            try:
-                from distributed import Client
-
-                Client.current(allow_global=True)
-                client_available = True
-            except (ImportError, ValueError):
-                client_available = False
+            client_available = False
+            if _distributed_available():
+                assert _DistributedClient is not None
+                with suppress(ValueError):
+                    _DistributedClient.current(allow_global=True)
+                    client_available = True
             if scheduler in named_schedulers:
                 if client_available:
                     warnings.warn(
@@ -1469,9 +1488,8 @@ def get_scheduler(get=None, scheduler=None, collections=None, cls=None):
                     raise RuntimeError(
                         f"Requested {scheduler} scheduler but no Client active."
                     )
-                from distributed.worker import get_client
-
-                return get_client().get
+                assert _get_distributed_client is not None
+                return _get_distributed_client().get
             else:
                 raise ValueError(
                     "Expected one of [distributed, %s]"
diff --git a/dask/dataframe/core.py b/dask/dataframe/core.py
index 3bbfb0839..e33c04ebf 100644
--- a/dask/dataframe/core.py
+++ b/dask/dataframe/core.py
@@ -5681,6 +5681,13 @@ class DataFrame(_Frame):
     def eval(self, expr, inplace=None, **kwargs):
         if inplace is None:
             inplace = False
+        else:
+            warnings.warn(
+                "`inplace` is deprecated and will be removed in a futuere version.",
+                FutureWarning,
+                2,
+            )
+
         if "=" in expr and inplace in (True, None):
             raise NotImplementedError(
                 "Inplace eval not supported. Please use inplace=False"
diff --git a/dask/dataframe/shuffle.py b/dask/dataframe/shuffle.py
index bc20025ac..5aceba651 100644
--- a/dask/dataframe/shuffle.py
+++ b/dask/dataframe/shuffle.py
@@ -219,6 +219,7 @@ def sort_values(
     return df
 
 
+@_deprecated_kwarg("compute", None)
 @_deprecated_kwarg("shuffle", "shuffle_method")
 def set_index(
     df: DataFrame,


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 89fc0b323..bae4badda 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -60,12 +60,14 @@ jobs:
         uses: actions/checkout@v4.1.1
         with:
           fetch-depth: 0  # Needed by codecov.io
+
       - name: Setup Java
         uses: actions/setup-java@v4
         if: ${{ matrix.os == 'ubuntu-latest' }}
         with:
           distribution: "zulu"
           java-version: "11"
+
       - name: Setup Conda Environment
         uses: conda-incubator/setup-miniconda@v3.0.1
         with:
@@ -89,14 +91,6 @@ jobs:
       - name: Install
         run: source continuous_integration/scripts/install.sh
 
-      # This environment file is created in continuous_integration/scripts/install.sh
-      # and can be useful when debugging locally
-      - name: Upload environment file
-        uses: actions/upload-artifact@v4
-        with:
-          name: env-${{ matrix.os }}-${{ matrix.environment }}-${{ matrix.extra }}
-          path: env.yaml
-
       - name: Run tests
         id: run_tests
         continue-on-error: ${{ matrix.extra == 'dask-expr' }}
@@ -105,24 +99,19 @@ jobs:
       - name: Coverage
         uses: codecov/codecov-action@v3
 
-      - name: Set $TEST_ID
-        if: >
-          always()
-        run: |
-          export TEST_ID="${{ matrix.os }}-${{ matrix.environment }}-${{ matrix.extra }}"
-          echo "TEST_ID: $TEST_ID"
-          echo "TEST_ID=$TEST_ID" >> $GITHUB_ENV
-        shell: bash
-
-      - name: Upload test results
+      # The environment file is created in continuous_integration/scripts/install.sh
+      # and can be useful when debugging locally
+      - name: Upload conda environment and test results
         # ensure this runs even if pytest fails
         if: >
           always() &&
           (steps.run_tests.outcome == 'success' || steps.run_tests.outcome == 'failure')
         uses: actions/upload-artifact@v4
         with:
-          name: test-results-${{ env.TEST_ID }}
-          path: pytest.xml
+          name: ${{ matrix.os }}-${{ matrix.environment }}-${{ matrix.extra }}
+          path: |
+            pytest.xml
+            env.yaml
 
   # Publish an artifact for the event; used by publish-test-results.yaml
   event_file:
diff --git a/dask/dataframe/tests/test_dataframe.py b/dask/dataframe/tests/test_dataframe.py
index 641242d93..6fc58b075 100644
--- a/dask/dataframe/tests/test_dataframe.py
+++ b/dask/dataframe/tests/test_dataframe.py
@@ -2824,6 +2824,7 @@ def test_query():
     )
 
 
+@pytest.mark.skipif(DASK_EXPR_ENABLED, reason="not available")
 def test_eval():
     pytest.importorskip("numexpr")
 
@@ -2831,8 +2832,15 @@ def test_eval():
     d = dd.from_pandas(p, npartitions=2)
 
     assert_eq(p.eval("x + y"), d.eval("x + y"))
-    assert_eq(p.eval("z = x + y", inplace=False), d.eval("z = x + y", inplace=False))
-    with pytest.raises(NotImplementedError):
+
+    deprecate_ctx = pytest.warns(FutureWarning, match="`inplace` is deprecated")
+
+    expected = p.eval("z = x + y", inplace=False)
+    with deprecate_ctx:
+        actual = d.eval("z = x + y", inplace=False)
+    assert_eq(expected, actual)
+
+    with pytest.raises(NotImplementedError), deprecate_ctx:
         d.eval("z = x + y", inplace=True)
 
 
diff --git a/dask/dataframe/tests/test_shuffle.py b/dask/dataframe/tests/test_shuffle.py
index 69dd7e29f..6cd28941d 100644
--- a/dask/dataframe/tests/test_shuffle.py
+++ b/dask/dataframe/tests/test_shuffle.py
@@ -519,16 +519,24 @@ def test_set_index_divisions_2():
 
 @pytest.mark.skipif(DASK_EXPR_ENABLED, reason="not available")
 def test_set_index_divisions_compute():
-    d2 = d.set_index("b", divisions=[0, 2, 9], compute=False)
-    d3 = d.set_index("b", divisions=[0, 2, 9], compute=True)
+    deprecated = pytest.warns(
+        FutureWarning, match="the 'compute' keyword is deprecated"
+    )
+
+    with deprecated:
+        d2 = d.set_index("b", divisions=[0, 2, 9], compute=False)
+    with deprecated:
+        d3 = d.set_index("b", divisions=[0, 2, 9], compute=True)
 
     assert_eq(d2, d3)
     assert_eq(d2, full.set_index("b"))
     assert_eq(d3, full.set_index("b"))
     assert len(d2.dask) > len(d3.dask)
 
-    d4 = d.set_index(d.b, divisions=[0, 2, 9], compute=False)
-    d5 = d.set_index(d.b, divisions=[0, 2, 9], compute=True)
+    with deprecated:
+        d4 = d.set_index(d.b, divisions=[0, 2, 9], compute=False)
+    with deprecated:
+        d5 = d.set_index(d.b, divisions=[0, 2, 9], compute=True)
     exp = full.copy()
     exp.index = exp.b
     assert_eq(d4, d5)