Repository: dask/dask

Issue:
`dask` fails to import when `tokenize.ensure-deterministic` is `True`
When `tokenize.ensure-deterministic` is set to `True`, `dask` fails to import

```python
DASK_TOKENIZE__ENSURE_DETERMINISTIC="True" python -c 'import dask; print(dask.__version__)'
Traceback (most recent call last):
  File "/Users/james/projects/dask/dask/dask/base.py", line 1037, in normalize_function
    return function_cache[func]
KeyError: <function right.<locals>._inner at 0x10ce74a60>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/james/projects/dask/dask/dask/__init__.py", line 12, in <module>
    from dask.delayed import delayed
  File "/Users/james/projects/dask/dask/dask/delayed.py", line 765, in <module>
    Delayed._bind_operator(op)
  File "/Users/james/projects/dask/dask/dask/utils.py", line 1299, in _bind_operator
    setattr(cls, rmeth, cls._get_binary_operator(op, inv=True))
  File "/Users/james/projects/dask/dask/dask/delayed.py", line 644, in _get_binary_operator
    method = delayed(right(op) if inv else op, pure=True)
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/Users/james/projects/dask/dask/dask/delayed.py", line 488, in delayed
    token = tokenize(obj, nout, pure=pure)
  File "/Users/james/projects/dask/dask/dask/delayed.py", line 261, in tokenize
    return _tokenize(*args, **kwargs)
  File "/Users/james/projects/dask/dask/dask/base.py", line 931, in tokenize
    hasher = _md5(str(tuple(map(normalize_token, args))).encode())
  File "/Users/james/projects/dask/dask/dask/utils.py", line 639, in __call__
    return meth(arg, *args, **kwargs)
  File "/Users/james/projects/dask/dask/dask/base.py", line 1016, in normalize_object
    return normalize_function(o)
  File "/Users/james/projects/dask/dask/dask/base.py", line 1039, in normalize_function
    result = _normalize_function(func)
  File "/Users/james/projects/dask/dask/dask/base.py", line 1080, in _normalize_function
    raise RuntimeError(
RuntimeError: Function <function right.<locals>._inner at 0x10ce74a60> may not be deterministically hashed by cloudpickle. See: https://github.com/cloudpipe/cloudpickle/issues/385 for more information.
```


Discussion:

Resolving patch:
diff --git a/dask/delayed.py b/dask/delayed.py
--- a/dask/delayed.py
+++ b/dask/delayed.py
@@ -4,6 +4,7 @@
 import warnings
 from collections.abc import Iterator
 from dataclasses import fields, is_dataclass, replace
+from functools import partial
 
 from tlz import concat, curry, merge, unique
 
@@ -496,13 +497,13 @@ def delayed(obj, name=None, pure=None, nout=None, traverse=True):
         return Delayed(name, graph, nout)
 
 
-def right(method):
-    """Wrapper to create 'right' version of operator given left version"""
+def _swap(method, self, other):
+    return method(other, self)
 
-    def _inner(self, other):
-        return method(other, self)
 
-    return _inner
+def right(method):
+    """Wrapper to create 'right' version of operator given left version"""
+    return partial(_swap, method)
 
 
 def optimize(dsk, keys, **kwargs):


Test patch:
diff --git a/continuous_integration/scripts/test_imports.sh b/continuous_integration/scripts/test_imports.sh
--- a/continuous_integration/scripts/test_imports.sh
+++ b/continuous_integration/scripts/test_imports.sh
@@ -15,6 +15,10 @@ test_import () {
     mamba list
     echo "python -c '$2'"
     python -c "$2"
+    # Ensure that no non-deterministic objects are tokenized at init time,
+    # which can prevent the library from being imported at all.
+    echo "python -c '$2' (ensure deterministic)"
+    DASK_TOKENIZE__ENSURE_DETERMINISTIC=True python -c "$2"
     conda deactivate
     mamba env remove -n test-imports
 }