bmerry: @jakirkham would you be able to review this?
TomAugspurger: Thank @bmerry, this looks good.

> This may have a minor performance impact because there is
now an extra per-chunk dictionary being thrown around.

As a sanity check, things look OK

```python
import dask.array as da

arr = da.random.random_integers(0, 10, size=(100_000, 100), chunks=100)

%timeit arr.map_blocks(lambda x, block_info=None: x)
%timeit arr.map_blocks(lambda x, block_info=None: x[:, 0], drop_axis=1)
```

I don't see any slowdown from master. Can you confirm that those should basically be the worst-case scenario for performance, since those functions basically do nothing?
bmerry: The performance drop I was referring to is comparing before and after this patch (both without `drop_axis`), rather than with vs without `drop_axis`. Modifying your test slightly to use more chunks:

```python
import dask.array as da

arr = da.random.random_integers(0, 10, size=(100_000, 100), chunks=10)

%timeit arr.map_blocks(lambda x, block_info=None: x)
```

I get 6.13 s ± 47.1 ms from 1.2.2 and 6.35 s ± 33 ms from this branch. So the difference is statistically significant but not very large.
diff --git a/dask/array/core.py b/dask/array/core.py
index f9fa56a15..40c6bc0a6 100644
--- a/dask/array/core.py
+++ b/dask/array/core.py
@@ -536,7 +536,7 @@ def map_blocks(func, *args, **kwargs):
         chunks2 = []
         for i, (c, nb) in enumerate(zip(chunks, out.numblocks)):
             if isinstance(c, tuple):
-                # We only check cases where numblocks > 1. Becuase of
+                # We only check cases where numblocks > 1. Because of
                 # broadcasting, we can't (easily) validate the chunks
                 # when the number of blocks is 1.
                 # See https://github.com/dask/dask/issues/4299 for more.
@@ -555,16 +555,19 @@ def map_blocks(func, *args, **kwargs):
         num_chunks = {}
         shapes = {}
 
-        for i, arg in enumerate(args):
-            if isinstance(arg, Array):
-                starts[i] = [np.cumsum((0,) + c) for c in arg.chunks]
+        for i, (arg, in_ind) in enumerate(argpairs):
+            if in_ind is not None:
                 shapes[i] = arg.shape
-                num_chunks[i] = arg.numblocks
-        for k, v in kwargs.items():
-            if isinstance(v, Array):
-                starts[k] = [np.cumsum((0,) + c) for c in v.chunks]
-                shapes[k] = arg.shape
-                num_chunks[i] = arg.numblocks
+                if drop_axis:
+                    # We concatenate along dropped axes, so we need to treat them
+                    # as if there is only a single chunk.
+                    starts[i] = [(np.cumsum((0,) + arg.chunks[j])
+                                  if ind in out_ind else np.array([0, arg.shape[j]]))
+                                 for j, ind in enumerate(in_ind)]
+                    num_chunks[i] = tuple(len(s) - 1 for s in starts[i])
+                else:
+                    starts[i] = [np.cumsum((0,) + c) for c in arg.chunks]
+                    num_chunks[i] = arg.numblocks
         out_starts = [np.cumsum((0,) + c) for c in out.chunks]
 
         for k, v in dsk.items():
@@ -572,21 +575,16 @@ def map_blocks(func, *args, **kwargs):
             v = v[0]
             [(key, task)] = v.dsk.items()  # unpack subgraph callable
 
-            if new_axis:
-                # anything using the keys in dsk is incorrect, as the
-                # original array doesn't have values for `new_axis`.
-                old_k = tuple(x for i, x in enumerate(k[1:]) if i not in new_axis)
-            else:
-                old_k = k[1:]
-
+            # Get position of chunk, indexed by axis labels
+            location = {out_ind[i]: loc for i, loc in enumerate(k[1:])}
             info = {}
             for i, shape in shapes.items():
                 # Compute chunk key in the array, taking broadcasting into
                 # account. We don't directly know which dimensions are
                 # broadcast, but any dimension with only one chunk can be
                 # treated as broadcast.
-                arr_k = old_k[-len(shape):]
-                arr_k = tuple(j if num_chunks[i][ij] > 1 else 0 for ij, j in enumerate(arr_k))
+                arr_k = tuple(location.get(ind, 0) if num_chunks[i][j] > 1 else 0
+                              for j, ind in enumerate(argpairs[i][1]))
                 info[i] = {'shape': shape,
                            'num-chunks': num_chunks[i],
                            'array-location': [(starts[i][ij][j], starts[i][ij][j + 1])
diff --git a/docs/source/setup.rst b/docs/source/setup.rst
index 60d71f3e3..818a46594 100644
--- a/docs/source/setup.rst
+++ b/docs/source/setup.rst
@@ -84,3 +84,4 @@ how to set up Dask on a variety of local and distributed hardware.
    setup/cloud.rst
    setup/adaptive.rst
    setup/docker.rst
+   setup/custom-startup.rst
diff --git a/docs/source/setup/custom-startup.rst b/docs/source/setup/custom-startup.rst
new file mode 100644
index 000000000..eebe92efb
--- /dev/null
+++ b/docs/source/setup/custom-startup.rst
@@ -0,0 +1,73 @@
+Custom Initialization
+=====================
+
+Often we want to run custom code when we start up or tear down a scheduler or
+worker.  We might do this manually with functions like ``Client.run`` or
+``Client.run_on_scheduler``, but this is error prone and difficult to automate.
+
+To resolve this, Dask includes a few mechanisms to run arbitrary code around
+the lifecycle of a Scheduler or Worker.
+
+Preload Scripts
+---------------
+
+Both ``dask-scheduler`` and ``dask-worker`` support a ``--preload`` option that
+allows custom initialization of each scheduler/worker respectively. A module or
+Python file passed as a ``--preload`` value is guaranteed to be imported before
+establishing any connection. A ``dask_setup(service)`` function is called if
+found, with a ``Scheduler`` or ``Worker`` instance as the argument. As the
+service stops, ``dask_teardown(service)`` is called if present.
+
+To support additional configuration, a single ``--preload`` module may register
+additional command-line arguments by exposing ``dask_setup`` as a  Click_
+command.  This command will be used to parse additional arguments provided to
+``dask-worker`` or ``dask-scheduler`` and will be called before service
+initialization.
+
+.. _Click: http://click.pocoo.org/
+
+
+As an example, consider the following file that creates a
+:doc:`scheduler plugin <plugins>` and registers it with the scheduler
+
+.. code-block:: python
+
+   # scheduler-setup.py
+   import click
+
+   from distributed.diagnostics.plugin import SchedulerPlugin
+
+   class MyPlugin(SchedulerPlugin):
+       def __init__(self, print_count):
+         self.print_count = print_count
+         SchedulerPlugin.__init__(self)
+
+       def add_worker(self, scheduler=None, worker=None, **kwargs):
+           print("Added a new worker at:", worker)
+           if self.print_count and scheduler is not None:
+               print("Total workers:", len(scheduler.workers))
+
+   @click.command()
+   @click.option("--print-count/--no-print-count", default=False)
+   def dask_setup(scheduler, print_count):
+       plugin = MyPlugin(print_count)
+       scheduler.add_plugin(plugin)
+
+We can then run this preload script by referring to its filename (or module name
+if it is on the path) when we start the scheduler::
+
+   dask-scheduler --preload scheduler-setup.py --print-count
+
+
+Worker Lifecycle Plugins
+------------------------
+
+You can also create a class with setup and teardown methods, and register that
+class with the scheduler to give to every worker.
+
+.. currentmodule:: distributed
+
+.. autosummary::
+   Client.register_worker_plugin
+
+.. automethod:: Client.register_worker_plugin

da.map_blocks with drop_axis stopped working in dask 1.1.4 
Hi!

First and foremost a big Thank You for the amazing work that you're doing with dask! It's a fantastic piece of software! 

We're using dask as parallelization engine for a large-scale data analysis package (still in early development). Our computational routines work on independent chunks of one big source data-set and then write to a single file (accessible to all workers). We used `map_blocks` for this in dask 1.0.0 and things worked great but unfortunately the same code does not work any more in dask 1.1.4. Here's a MCVE:

```python
import dask
import dask.array as da
import numpy as np

# in reality used to write `chk` to a (pre-formatted) file
def da_dummy(chk, block_info=None):
    idx = block_info[0]["chunk-location"][-1]
    #
    # use `idx` to store `chk` at correct location
    # 
    return idx

np_a = np.ones((10,50*20))
a = da.from_array(np_a, chunks=(10,20))

# works in dask 1.0.0, raises an IndexError in dask 1.1.4
result = a.map_blocks(da_dummy, dtype="int", chunks=(1,), drop_axis=[0])
res = result.compute()
```
In dask 1.0.0 this snippet produces an array `res` that looks like this:
```python
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
       34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49])
```
In dask 1.1.4 the same code triggers an `IndexError: index 2 is out of bounds for axis 0 with size 2`, here the full traceback:

<details>

```python
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/Documents/job/dask_fail.py in <module>
     15 
     16 # works in dask 1.0.0, raises an IndexError in dask 1.1.4
---> 17 result = a.map_blocks(da_dummy, dtype="int", chunks=(1,), drop_axis=[0])
     18 res = result.compute()
     19 

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in map_blocks(self, func, *args, **kwargs)
   1569     @wraps(map_blocks)
   1570     def map_blocks(self, func, *args, **kwargs):
-> 1571         return map_blocks(func, self, *args, **kwargs)
   1572 
   1573     def map_overlap(self, func, depth, boundary=None, trim=True, **kwargs):

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in map_blocks(func, *args, **kwargs)
    534                                            for ij, j in enumerate(old_k[1:])],
    535                         'chunk-location': old_k[1:]}
--> 536                     for i in shapes}
    537 
    538             v = copy.copy(v)  # Need to copy and unpack subgraph callable

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in <dictcomp>(.0)
    534                                            for ij, j in enumerate(old_k[1:])],
    535                         'chunk-location': old_k[1:]}
--> 536                     for i in shapes}
    537 
    538             v = copy.copy(v)  # Need to copy and unpack subgraph callable

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in <listcomp>(.0)
    532                         'num-chunks': num_chunks[i],
    533                         'array-location': [(starts[i][ij][j], starts[i][ij][j + 1])
--> 534                                            for ij, j in enumerate(old_k[1:])],
    535                         'chunk-location': old_k[1:]}
    536                     for i in shapes}

IndexError: index 2 is out of bounds for axis 0 with size 2
```

</details>

A (desperate) attempt at somehow working around this was to not use `drop_axis` and instead leave the chunk-size as is and return a bogus tuple, but no luck either:

```python

import dask
import dask.array as da
import numpy as np

np_a = np.ones((10,50*20))
a = da.from_array(np_a, chunks=(10,20))

# desperate workaround for dask 1.1.4 - still not working
def da_dummy2(chk, block_info=None):
    print(block_info) # show what's going on in here...
    idx = block_info[0]["chunk-location"][-1]
    return (idx, 1)
result = a.map_blocks(da_dummy2, dtype="int", chunks=(1, 1))
res = result.compute()
```

This gives an `IndexError: tuple index out of range`, full traceback here:

<details>

```python
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
~/Documents/job/dask_fail.py in <module>
     20     return (idx, 1)
     21 result = a.map_blocks(da_dummy2, dtype="int", chunks=(1, 1))
---> 22 res = result.compute()
     23 

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/base.py in compute(self, **kwargs)
    154         dask.base.compute
    155         """
--> 156         (result,) = compute(self, traverse=False, **kwargs)
    157         return result
    158 

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/base.py in compute(*args, **kwargs)
    397     postcomputes = [x.__dask_postcompute__() for x in collections]
    398     results = schedule(dsk, keys, **kwargs)
--> 399     return repack([f(r, *a) for r, (f, a) in zip(results, postcomputes)])
    400 
    401 

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/base.py in <listcomp>(.0)
    397     postcomputes = [x.__dask_postcompute__() for x in collections]
    398     results = schedule(dsk, keys, **kwargs)
--> 399     return repack([f(r, *a) for r, (f, a) in zip(results, postcomputes)])
    400 
    401 

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in finalize(results)
    777     while isinstance(results2, (tuple, list)):
    778         if len(results2) > 1:
--> 779             return concatenate3(results)
    780         else:
    781             results2 = results2[0]

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in concatenate3(arrays)
   3495     if not ndim:
   3496         return arrays
-> 3497     chunks = chunks_from_arrays(arrays)
   3498     shape = tuple(map(sum, chunks))
   3499 

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in chunks_from_arrays(arrays)
   3325 
   3326     while isinstance(arrays, (list, tuple)):
-> 3327         result.append(tuple([shape(deepfirst(a))[dim] for a in arrays]))
   3328         arrays = arrays[0]
   3329         dim += 1

/usr/local/software/anaconda/envs/p3/lib/python3.6/site-packages/dask/array/core.py in <listcomp>(.0)
   3325 
   3326     while isinstance(arrays, (list, tuple)):
-> 3327         result.append(tuple([shape(deepfirst(a))[dim] for a in arrays]))
   3328         arrays = arrays[0]
   3329         dim += 1

IndexError: tuple index out of range
```

</details>

Any help with this is greatly appreciated. Thank you! 
diff --git a/dask/array/tests/test_array_core.py b/dask/array/tests/test_array_core.py
index b4b5cc30d..2da84ff96 100644
--- a/dask/array/tests/test_array_core.py
+++ b/dask/array/tests/test_array_core.py
@@ -1115,7 +1115,7 @@ def test_map_blocks_block_info():
     assert_eq(z, x + x + 1 + 100)
 
 
-def test_map_blocks_block_info_with_axis():
+def test_map_blocks_block_info_with_new_axis():
     # https://github.com/dask/dask/issues/4298
     values = da.from_array(np.array(['a', 'a', 'b', 'c']), 2)
 
@@ -1145,6 +1145,40 @@ def test_map_blocks_block_info_with_axis():
     assert_eq(z, np.ones((4, 3), dtype='f8'))
 
 
+def test_map_blocks_block_info_with_drop_axis():
+    # https://github.com/dask/dask/issues/4584
+    values = da.from_array(np.array([[1, 2, 4],
+                                     [8, 16, 32],
+                                     [64, 128, 256],
+                                     [1024, 2048, 4096]], dtype='u4'), (2, 1))
+
+    def func(x, block_info=None):
+        assert set(block_info.keys()) == {0, None}
+        assert block_info[0]['shape'] == (4, 3)
+        # drop_axis concatenates along the dropped dimension, hence not (2, 3)
+        assert block_info[0]['num-chunks'] == (2, 1)
+        assert block_info[None]['shape'] == (4,)
+        assert block_info[None]['num-chunks'] == (2,)
+        assert block_info[None]['chunk-shape'] == (2,)
+        assert block_info[None]['dtype'] == np.dtype('u4')
+
+        assert block_info[0]['chunk-location'] in {(0, 0), (1, 0)}
+
+        if block_info[0]['chunk-location'] == (0, 0):
+            assert block_info[0]['array-location'] == [(0, 2), (0, 3)]
+            assert block_info[None]['chunk-location'] == (0,)
+            assert block_info[None]['array-location'] == [(0, 2)]
+        elif block_info[0]['chunk-location'] == (1, 0):
+            assert block_info[0]['array-location'] == [(2, 4), (0, 3)]
+            assert block_info[None]['chunk-location'] == (1,)
+            assert block_info[None]['array-location'] == [(2, 4)]
+
+        return np.sum(x, axis=1, dtype='u4')
+
+    z = values.map_blocks(func, drop_axis=1, dtype='u4')
+    assert_eq(z, np.array([7, 56, 448, 7168], dtype='u4'))
+
+
 def test_map_blocks_block_info_with_broadcast():
     expected0 = [
         {'shape': (3, 4), 'num-chunks': (1, 2), 'array-location': [(0, 3), (0, 2)], 'chunk-location': (0, 0)},

pip install -e .[complete]
parse_log_pytest
pytest
pytest
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
certifi==2021.5.30
click==8.0.4
cloudpickle==2.2.1
-e git+https://github.com/dask/dask.git@01fe81fe8ee020acdd6296a72b33e81dfd4ed4b6#egg=dask
distributed==1.28.1
HeapDict==1.0.1
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
locket==1.0.0
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
msgpack==1.0.5
numpy==1.19.5
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pandas==1.1.5
partd==1.2.0
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
psutil==7.0.0
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==6.0.1
six==1.17.0
sortedcontainers==2.4.0
tblib==1.7.0
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
toolz==0.12.0
tornado==6.1
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
zict==2.1.0
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: dask
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=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:
      - click==8.0.4
      - cloudpickle==2.2.1
      - distributed==1.28.1
      - heapdict==1.0.1
      - locket==1.0.0
      - msgpack==1.0.5
      - numpy==1.19.5
      - pandas==1.1.5
      - partd==1.2.0
      - psutil==7.0.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==6.0.1
      - six==1.17.0
      - sortedcontainers==2.4.0
      - tblib==1.7.0
      - toolz==0.12.0
      - tornado==6.1
      - zict==2.1.0
prefix: /opt/conda/envs/dask

dask/array/tests/test_array_core.py::test_map_blocks_block_info_with_drop_axis
dask/array/tests/test_array_core.py::test_concatenate_unknown_axes dask/array/tests/test_array_core.py::test_to_dask_dataframe dask/array/tests/test_array_core.py::test_asarray_dask_dataframe dask/array/tests/test_array_core.py::test_asanyarray_dataframe
dask/array/tests/test_array_core.py::test_getem dask/array/tests/test_array_core.py::test_top dask/array/tests/test_array_core.py::test_top_supports_broadcasting_rules dask/array/tests/test_array_core.py::test_top_literals dask/array/tests/test_array_core.py::test_blockwise_literals dask/array/tests/test_array_core.py::test_concatenate3_on_scalars dask/array/tests/test_array_core.py::test_chunked_dot_product dask/array/tests/test_array_core.py::test_chunked_transpose_plus_one dask/array/tests/test_array_core.py::test_broadcast_dimensions_works_with_singleton_dimensions dask/array/tests/test_array_core.py::test_broadcast_dimensions dask/array/tests/test_array_core.py::test_Array dask/array/tests/test_array_core.py::test_uneven_chunks dask/array/tests/test_array_core.py::test_numblocks_suppoorts_singleton_block_dims dask/array/tests/test_array_core.py::test_keys dask/array/tests/test_array_core.py::test_Array_computation dask/array/tests/test_array_core.py::test_stack dask/array/tests/test_array_core.py::test_short_stack dask/array/tests/test_array_core.py::test_stack_scalars dask/array/tests/test_array_core.py::test_stack_promote_type dask/array/tests/test_array_core.py::test_stack_rechunk dask/array/tests/test_array_core.py::test_concatenate dask/array/tests/test_array_core.py::test_concatenate_types[dtypes0] dask/array/tests/test_array_core.py::test_concatenate_types[dtypes1] dask/array/tests/test_array_core.py::test_concatenate_rechunk dask/array/tests/test_array_core.py::test_concatenate_fixlen_strings dask/array/tests/test_array_core.py::test_block_simple_row_wise dask/array/tests/test_array_core.py::test_block_simple_column_wise dask/array/tests/test_array_core.py::test_block_with_1d_arrays_row_wise dask/array/tests/test_array_core.py::test_block_with_1d_arrays_multiple_rows dask/array/tests/test_array_core.py::test_block_with_1d_arrays_column_wise dask/array/tests/test_array_core.py::test_block_mixed_1d_and_2d dask/array/tests/test_array_core.py::test_block_complicated dask/array/tests/test_array_core.py::test_block_nested dask/array/tests/test_array_core.py::test_block_3d dask/array/tests/test_array_core.py::test_block_with_mismatched_shape dask/array/tests/test_array_core.py::test_block_no_lists dask/array/tests/test_array_core.py::test_block_invalid_nesting dask/array/tests/test_array_core.py::test_block_empty_lists dask/array/tests/test_array_core.py::test_block_tuple dask/array/tests/test_array_core.py::test_broadcast_shapes dask/array/tests/test_array_core.py::test_elemwise_on_scalars dask/array/tests/test_array_core.py::test_elemwise_with_ndarrays dask/array/tests/test_array_core.py::test_elemwise_differently_chunked dask/array/tests/test_array_core.py::test_elemwise_dtype dask/array/tests/test_array_core.py::test_operators dask/array/tests/test_array_core.py::test_operator_dtype_promotion dask/array/tests/test_array_core.py::test_field_access dask/array/tests/test_array_core.py::test_field_access_with_shape dask/array/tests/test_array_core.py::test_matmul dask/array/tests/test_array_core.py::test_matmul_array_ufunc dask/array/tests/test_array_core.py::test_T dask/array/tests/test_array_core.py::test_broadcast_to dask/array/tests/test_array_core.py::test_broadcast_to_array dask/array/tests/test_array_core.py::test_broadcast_to_scalar dask/array/tests/test_array_core.py::test_broadcast_to_chunks dask/array/tests/test_array_core.py::test_broadcast_arrays dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape0-v_shape0] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape1-v_shape1] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape2-v_shape2] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape3-v_shape3] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape4-v_shape4] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape5-v_shape5] dask/array/tests/test_array_core.py::test_broadcast_operator[u_shape6-v_shape6] dask/array/tests/test_array_core.py::test_reshape[original_shape0-new_shape0-chunks0] dask/array/tests/test_array_core.py::test_reshape[original_shape1-new_shape1-5] dask/array/tests/test_array_core.py::test_reshape[original_shape2-new_shape2-5] dask/array/tests/test_array_core.py::test_reshape[original_shape3-new_shape3-12] dask/array/tests/test_array_core.py::test_reshape[original_shape4-new_shape4-12] dask/array/tests/test_array_core.py::test_reshape[original_shape5-new_shape5-chunks5] dask/array/tests/test_array_core.py::test_reshape[original_shape6-new_shape6-4] dask/array/tests/test_array_core.py::test_reshape[original_shape7-new_shape7-4] dask/array/tests/test_array_core.py::test_reshape[original_shape8-new_shape8-4] dask/array/tests/test_array_core.py::test_reshape[original_shape9-new_shape9-2] dask/array/tests/test_array_core.py::test_reshape[original_shape10-new_shape10-2] dask/array/tests/test_array_core.py::test_reshape[original_shape11-new_shape11-2] dask/array/tests/test_array_core.py::test_reshape[original_shape12-new_shape12-2] dask/array/tests/test_array_core.py::test_reshape[original_shape13-new_shape13-2] dask/array/tests/test_array_core.py::test_reshape[original_shape14-new_shape14-2] dask/array/tests/test_array_core.py::test_reshape[original_shape15-new_shape15-2] dask/array/tests/test_array_core.py::test_reshape[original_shape16-new_shape16-chunks16] dask/array/tests/test_array_core.py::test_reshape[original_shape17-new_shape17-3] dask/array/tests/test_array_core.py::test_reshape[original_shape18-new_shape18-4] dask/array/tests/test_array_core.py::test_reshape[original_shape19-new_shape19-chunks19] dask/array/tests/test_array_core.py::test_reshape[original_shape20-new_shape20-1] dask/array/tests/test_array_core.py::test_reshape[original_shape21-new_shape21-1] dask/array/tests/test_array_core.py::test_reshape[original_shape22-new_shape22-24] dask/array/tests/test_array_core.py::test_reshape[original_shape23-new_shape23-6] dask/array/tests/test_array_core.py::test_reshape[original_shape24-new_shape24-6] dask/array/tests/test_array_core.py::test_reshape[original_shape25-new_shape25-6] dask/array/tests/test_array_core.py::test_reshape[original_shape26-new_shape26-chunks26] dask/array/tests/test_array_core.py::test_reshape[original_shape27-new_shape27-chunks27] dask/array/tests/test_array_core.py::test_reshape[original_shape28-new_shape28-chunks28] dask/array/tests/test_array_core.py::test_reshape[original_shape29-new_shape29-chunks29] dask/array/tests/test_array_core.py::test_reshape[original_shape30-new_shape30-chunks30] dask/array/tests/test_array_core.py::test_reshape[original_shape31-new_shape31-chunks31] dask/array/tests/test_array_core.py::test_reshape[original_shape32-new_shape32-chunks32] dask/array/tests/test_array_core.py::test_reshape[original_shape33-new_shape33-chunks33] dask/array/tests/test_array_core.py::test_reshape[original_shape34-new_shape34-chunks34] dask/array/tests/test_array_core.py::test_reshape_exceptions dask/array/tests/test_array_core.py::test_reshape_splat dask/array/tests/test_array_core.py::test_reshape_fails_for_dask_only dask/array/tests/test_array_core.py::test_reshape_unknown_dimensions dask/array/tests/test_array_core.py::test_full dask/array/tests/test_array_core.py::test_map_blocks dask/array/tests/test_array_core.py::test_map_blocks2 dask/array/tests/test_array_core.py::test_map_blocks_block_info dask/array/tests/test_array_core.py::test_map_blocks_block_info_with_new_axis dask/array/tests/test_array_core.py::test_map_blocks_block_info_with_broadcast dask/array/tests/test_array_core.py::test_map_blocks_with_constants dask/array/tests/test_array_core.py::test_map_blocks_with_kwargs dask/array/tests/test_array_core.py::test_map_blocks_with_chunks dask/array/tests/test_array_core.py::test_map_blocks_dtype_inference dask/array/tests/test_array_core.py::test_map_blocks_infer_newaxis dask/array/tests/test_array_core.py::test_map_blocks_no_array_args dask/array/tests/test_array_core.py::test_repr dask/array/tests/test_array_core.py::test_slicing_with_ellipsis dask/array/tests/test_array_core.py::test_slicing_with_ndarray dask/array/tests/test_array_core.py::test_dtype dask/array/tests/test_array_core.py::test_blockdims_from_blockshape dask/array/tests/test_array_core.py::test_coerce dask/array/tests/test_array_core.py::test_bool dask/array/tests/test_array_core.py::test_store_kwargs dask/array/tests/test_array_core.py::test_store_delayed_target dask/array/tests/test_array_core.py::test_store dask/array/tests/test_array_core.py::test_store_regions dask/array/tests/test_array_core.py::test_store_compute_false dask/array/tests/test_array_core.py::test_store_nocompute_regions dask/array/tests/test_array_core.py::test_store_locks dask/array/tests/test_array_core.py::test_store_method_return dask/array/tests/test_array_core.py::test_np_array_with_zero_dimensions dask/array/tests/test_array_core.py::test_dtype_complex dask/array/tests/test_array_core.py::test_astype dask/array/tests/test_array_core.py::test_arithmetic dask/array/tests/test_array_core.py::test_elemwise_consistent_names dask/array/tests/test_array_core.py::test_optimize dask/array/tests/test_array_core.py::test_slicing_with_non_ndarrays dask/array/tests/test_array_core.py::test_getter dask/array/tests/test_array_core.py::test_size dask/array/tests/test_array_core.py::test_nbytes dask/array/tests/test_array_core.py::test_itemsize dask/array/tests/test_array_core.py::test_Array_normalizes_dtype dask/array/tests/test_array_core.py::test_from_array_with_lock dask/array/tests/test_array_core.py::test_from_array_tasks_always_call_getter[x0-chunks0] dask/array/tests/test_array_core.py::test_from_array_tasks_always_call_getter[x1--1] dask/array/tests/test_array_core.py::test_from_array_tasks_always_call_getter[x2-1] dask/array/tests/test_array_core.py::test_from_array_tasks_always_call_getter[x3-1] dask/array/tests/test_array_core.py::test_from_array_ndarray_onechunk dask/array/tests/test_array_core.py::test_from_array_ndarray_getitem dask/array/tests/test_array_core.py::test_from_array_list[x0] dask/array/tests/test_array_core.py::test_from_array_list[x1] dask/array/tests/test_array_core.py::test_from_array_list[x2] dask/array/tests/test_array_core.py::test_from_array_scalar[int0] dask/array/tests/test_array_core.py::test_from_array_scalar[float] dask/array/tests/test_array_core.py::test_from_array_scalar[complex] dask/array/tests/test_array_core.py::test_from_array_scalar[int1] dask/array/tests/test_array_core.py::test_from_array_scalar[bool] dask/array/tests/test_array_core.py::test_from_array_scalar[bytes] dask/array/tests/test_array_core.py::test_from_array_scalar[str] dask/array/tests/test_array_core.py::test_from_array_scalar[object_] dask/array/tests/test_array_core.py::test_from_array_scalar[datetime64] dask/array/tests/test_array_core.py::test_from_array_scalar[ulonglong] dask/array/tests/test_array_core.py::test_from_array_scalar[longlong] dask/array/tests/test_array_core.py::test_from_array_scalar[void] dask/array/tests/test_array_core.py::test_from_array_scalar[complex256] dask/array/tests/test_array_core.py::test_from_array_scalar[float128] dask/array/tests/test_array_core.py::test_from_array_scalar[uint64] dask/array/tests/test_array_core.py::test_from_array_scalar[int64] dask/array/tests/test_array_core.py::test_from_array_scalar[str_] dask/array/tests/test_array_core.py::test_from_array_scalar[complex128] dask/array/tests/test_array_core.py::test_from_array_scalar[float64] dask/array/tests/test_array_core.py::test_from_array_scalar[uint32] dask/array/tests/test_array_core.py::test_from_array_scalar[int32] dask/array/tests/test_array_core.py::test_from_array_scalar[bytes_] dask/array/tests/test_array_core.py::test_from_array_scalar[complex64] dask/array/tests/test_array_core.py::test_from_array_scalar[float32] dask/array/tests/test_array_core.py::test_from_array_scalar[uint16] dask/array/tests/test_array_core.py::test_from_array_scalar[int16] dask/array/tests/test_array_core.py::test_from_array_scalar[bool_] dask/array/tests/test_array_core.py::test_from_array_scalar[timedelta64] dask/array/tests/test_array_core.py::test_from_array_scalar[float16] dask/array/tests/test_array_core.py::test_from_array_scalar[uint8] dask/array/tests/test_array_core.py::test_from_array_scalar[int8] dask/array/tests/test_array_core.py::test_from_array_no_asarray[True-ndarray] dask/array/tests/test_array_core.py::test_from_array_no_asarray[False-matrix] dask/array/tests/test_array_core.py::test_from_array_getitem dask/array/tests/test_array_core.py::test_from_array_minus_one dask/array/tests/test_array_core.py::test_from_array_copy dask/array/tests/test_array_core.py::test_asarray dask/array/tests/test_array_core.py::test_asanyarray dask/array/tests/test_array_core.py::test_from_func dask/array/tests/test_array_core.py::test_concatenate3_2 dask/array/tests/test_array_core.py::test_map_blocks3 dask/array/tests/test_array_core.py::test_from_array_with_missing_chunks dask/array/tests/test_array_core.py::test_normalize_chunks dask/array/tests/test_array_core.py::test_align_chunks_to_previous_chunks dask/array/tests/test_array_core.py::test_raise_on_no_chunks dask/array/tests/test_array_core.py::test_chunks_is_immutable dask/array/tests/test_array_core.py::test_raise_on_bad_kwargs dask/array/tests/test_array_core.py::test_long_slice dask/array/tests/test_array_core.py::test_ellipsis_slicing dask/array/tests/test_array_core.py::test_point_slicing dask/array/tests/test_array_core.py::test_point_slicing_with_full_slice dask/array/tests/test_array_core.py::test_slice_with_floats dask/array/tests/test_array_core.py::test_slice_with_integer_types dask/array/tests/test_array_core.py::test_index_with_integer_types dask/array/tests/test_array_core.py::test_vindex_basic dask/array/tests/test_array_core.py::test_vindex_nd dask/array/tests/test_array_core.py::test_vindex_negative dask/array/tests/test_array_core.py::test_vindex_errors dask/array/tests/test_array_core.py::test_vindex_merge dask/array/tests/test_array_core.py::test_vindex_identity dask/array/tests/test_array_core.py::test_empty_array dask/array/tests/test_array_core.py::test_memmap dask/array/tests/test_array_core.py::test_to_npy_stack dask/array/tests/test_array_core.py::test_view dask/array/tests/test_array_core.py::test_view_fortran dask/array/tests/test_array_core.py::test_map_blocks_with_changed_dimension dask/array/tests/test_array_core.py::test_map_blocks_with_changed_dimension_and_broadcast_chunks dask/array/tests/test_array_core.py::test_broadcast_chunks dask/array/tests/test_array_core.py::test_chunks_error dask/array/tests/test_array_core.py::test_array_compute_forward_kwargs dask/array/tests/test_array_core.py::test_dont_fuse_outputs dask/array/tests/test_array_core.py::test_dont_dealias_outputs dask/array/tests/test_array_core.py::test_timedelta_op dask/array/tests/test_array_core.py::test_to_delayed dask/array/tests/test_array_core.py::test_to_delayed_optimize_graph dask/array/tests/test_array_core.py::test_cumulative dask/array/tests/test_array_core.py::test_from_delayed dask/array/tests/test_array_core.py::test_A_property dask/array/tests/test_array_core.py::test_copy_mutate dask/array/tests/test_array_core.py::test_npartitions dask/array/tests/test_array_core.py::test_astype_gh1151 dask/array/tests/test_array_core.py::test_elemwise_name dask/array/tests/test_array_core.py::test_map_blocks_name dask/array/tests/test_array_core.py::test_from_array_names dask/array/tests/test_array_core.py::test_array_picklable dask/array/tests/test_array_core.py::test_from_array_raises_on_bad_chunks dask/array/tests/test_array_core.py::test_concatenate_axes dask/array/tests/test_array_core.py::test_blockwise_concatenate dask/array/tests/test_array_core.py::test_common_blockdim dask/array/tests/test_array_core.py::test_uneven_chunks_that_fit_neatly dask/array/tests/test_array_core.py::test_elemwise_uneven_chunks dask/array/tests/test_array_core.py::test_uneven_chunks_blockwise dask/array/tests/test_array_core.py::test_warn_bad_rechunking dask/array/tests/test_array_core.py::test_concatenate_stack_dont_warn dask/array/tests/test_array_core.py::test_map_blocks_delayed dask/array/tests/test_array_core.py::test_no_chunks dask/array/tests/test_array_core.py::test_no_chunks_2d dask/array/tests/test_array_core.py::test_no_chunks_yes_chunks dask/array/tests/test_array_core.py::test_raise_informative_errors_no_chunks dask/array/tests/test_array_core.py::test_no_chunks_slicing_2d dask/array/tests/test_array_core.py::test_index_array_with_array_1d dask/array/tests/test_array_core.py::test_index_array_with_array_2d dask/array/tests/test_array_core.py::test_setitem_1d dask/array/tests/test_array_core.py::test_setitem_2d dask/array/tests/test_array_core.py::test_setitem_errs dask/array/tests/test_array_core.py::test_zero_slice_dtypes dask/array/tests/test_array_core.py::test_zero_sized_array_rechunk dask/array/tests/test_array_core.py::test_blockwise_zero_shape dask/array/tests/test_array_core.py::test_blockwise_zero_shape_new_axes dask/array/tests/test_array_core.py::test_broadcast_against_zero_shape dask/array/tests/test_array_core.py::test_from_array_name dask/array/tests/test_array_core.py::test_concatenate_errs dask/array/tests/test_array_core.py::test_stack_errs dask/array/tests/test_array_core.py::test_blockwise_with_numpy_arrays dask/array/tests/test_array_core.py::test_elemwise_with_lists[other0-100] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other0-6] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other1-100] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other1-6] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other2-100] dask/array/tests/test_array_core.py::test_elemwise_with_lists[other2-6] dask/array/tests/test_array_core.py::test_constructor_plugin dask/array/tests/test_array_core.py::test_no_warnings_on_metadata dask/array/tests/test_array_core.py::test_delayed_array_key_hygeine dask/array/tests/test_array_core.py::test_empty_chunks_in_array_len dask/array/tests/test_array_core.py::test_meta[None] dask/array/tests/test_array_core.py::test_meta[dtype1] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_1d[100-10-expected0] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_1d[20-10-expected1] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_1d[20-5-expected2] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_1d[24-5-expected3] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_1d[23-5-expected4] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_1d[1000-167-expected5] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_2d[shape0-chunks0-20-expected0] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_2d[shape1-chunks1-20-expected1] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_2d[shape2-auto-10-expected2] dask/array/tests/test_array_core.py::test_normalize_chunks_auto_3d dask/array/tests/test_array_core.py::test_constructors_chunks_dict dask/array/tests/test_array_core.py::test_from_array_chunks_dict dask/array/tests/test_array_core.py::test_normalize_chunks_object_dtype[object] dask/array/tests/test_array_core.py::test_normalize_chunks_object_dtype[dtype1] dask/array/tests/test_array_core.py::test_normalize_chunks_tuples_of_tuples dask/array/tests/test_array_core.py::test_normalize_chunks_nan dask/array/tests/test_array_core.py::test_regular_chunks[data0] dask/array/tests/test_array_core.py::test_regular_chunks[data1] dask/array/tests/test_array_core.py::test_regular_chunks[data2] dask/array/tests/test_array_core.py::test_regular_chunks[data3] dask/array/tests/test_array_core.py::test_regular_chunks[data4] dask/array/tests/test_array_core.py::test_regular_chunks[data5] dask/array/tests/test_array_core.py::test_regular_chunks[data6] dask/array/tests/test_array_core.py::test_regular_chunks[data7] dask/array/tests/test_array_core.py::test_blocks_indexer dask/array/tests/test_array_core.py::test_3851 dask/array/tests/test_array_core.py::test_3925 dask/array/tests/test_array_core.py::test_map_blocks_large_inputs_delayed dask/array/tests/test_array_core.py::test_blockwise_large_inputs_delayed dask/array/tests/test_array_core.py::test_slice_reversed dask/array/tests/test_array_core.py::test_map_blocks_chunks dask/array/tests/test_array_core.py::test_nbytes_auto
docs/source/setup/custom-startup.rst dask/array/core.py docs/source/setup.rst
docs/source/setup/custom-startup.rst dask/array/core.py docs/source/setup.rst