Skip to content

feat: add Array API support via array-api-compat - #4179

Draft
amalia-k510 wants to merge 31 commits into
scverse:mainfrom
amalia-k510:array-api-compat-integration
Draft

feat: add Array API support via array-api-compat#4179
amalia-k510 wants to merge 31 commits into
scverse:mainfrom
amalia-k510:array-api-compat-integration

Conversation

@amalia-k510

Copy link
Copy Markdown
Contributor

This adds Array API support to scanpy's preprocessing pipeline, where I am planning to use JAX as the test case. The goal is for someone to put a JAX array into adata.X and run the usual pipeline without the array getting silently pulled to CPU partway through. It builds on the recent fast-array-utils work, which means a lot of the heavy lifting (sums, means, variances) already works across backends.

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

❌ 15 Tests Failed:

Tests completed Failed Passed Skipped
2853 15 2838 259
View the top 3 failed test(s) by shortest run time
tests/test_pca.py::tests.test_pca
Stack Traces | 0s run time
#x1B[1m#x1B[31mtests/test_pca.py#x1B[0m:196: in <module>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m svd_solver, warn_pat_expected, xfail_reason #x1B[95min#x1B[39;49;00m gen_pca_params(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mtests/test_pca.py#x1B[0m:111: in gen_pca_params
    #x1B[0msvd_solvers, warn_pat_expected = possible_solvers(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mtests/test_pca.py#x1B[0m:159: in possible_solvers
    #x1B[0msvd_solvers = {#x1B[33m"#x1B[39;49;00m#x1B[33mauto#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mfull#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33marpack#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mrandomized#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m} | SKLEARN_ADDITIONAL#x1B[90m#x1B[39;49;00m
                                                             ^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE   NameError: name 'SKLEARN_ADDITIONAL' is not defined#x1B[0m
tests/test_highly_variable_genes.py::test_compare_to_upstream[jax_array-cell_ranger]
Stack Traces | 0.014s run time
request = <FixtureRequest for <Function test_compare_to_upstream[jax_array-cell_ranger]>>
flavor = 'cell_ranger', params = {'n_top_genes': 100}
ref_path = PosixPath('.../tests/_scripts/cell_ranger_hvg.csv')
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mref_path#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[96mdict#x1B[39;49;00m(min_mean=#x1B[94m0.0125#x1B[39;49;00m, max_mean=#x1B[94m3#x1B[39;49;00m, min_disp=#x1B[94m0.5#x1B[39;49;00m), FILE, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            ),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[96mdict#x1B[39;49;00m(n_top_genes=#x1B[94m100#x1B[39;49;00m), FILE_CELL_RANGER, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            ),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_compare_to_upstream#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        request: pytest.FixtureRequest,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        params: Any,#x1B[90m#x1B[39;49;00m
        ref_path: Path,#x1B[90m#x1B[39;49;00m
        array_type: Callable,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        hvg_info = pd.read_csv(ref_path)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        pbmc.X = pbmc.raw.X#x1B[90m#x1B[39;49;00m
        pbmc.X = array_type(pbmc.X)#x1B[90m#x1B[39;49;00m
        pbmc.var_names_make_unique()#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_cells(pbmc, min_counts=#x1B[94m1#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:393: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:167: in filter_cells
    #x1B[0madata._inplace_subset_obs(cell_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1241: in _inplace_subset_obs
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,... True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[batch-jax_array-seurat_v3_paper]
Stack Traces | 0.032s run time
subtests = <_pytest.subtests.Subtests object at 0x7f9bb04077d0>
flavor = 'seurat_v3_paper'
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>
batch_key = 'batch'

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:787: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:185: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = aggregate(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/get/_aggregated.py#x1B[0m:386: in aggregate
    #x1B[0mlayers = _aggregate(data, by=categorical, func=func, mask=mask, dof=dof)#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

data = Array([[0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=int64)
by = ['b', 'b', 'b', 'a', 'a', ..., 'a', 'a', 'b', 'b', 'a']
Length: 1500
Categories (2, str): ['a', 'b']
func = ['mean', 'var'], mask = None, dof = 1

    #x1B[0m#x1B[37m@singledispatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_aggregate#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        data,#x1B[90m#x1B[39;49;00m
        by: pd.Categorical,#x1B[90m#x1B[39;49;00m
        func: AggType | Iterable[AggType],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        mask: NDArray[np.bool] | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        dof: #x1B[96mint#x1B[39;49;00m = #x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[96mdict#x1B[39;49;00m[AggType, np.ndarray | DaskArray]:#x1B[90m#x1B[39;49;00m
        msg = #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mData type #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mtype#x1B[39;49;00m(data)#x1B[33m}#x1B[39;49;00m#x1B[33m not supported for aggregation#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>       #x1B[94mraise#x1B[39;49;00m #x1B[96mNotImplementedError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE       NotImplementedError: Data type <class 'jaxlib._jax.ArrayImpl'> not supported for aggregation#x1B[0m

#x1B[1m#x1B[.../scanpy/get/_aggregated.py#x1B[0m:417: NotImplementedError
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-jax_array-seurat_v3]
Stack Traces | 0.038s run time
subtests = <_pytest.subtests.Subtests object at 0x7f9bc094fcb0>
flavor = 'seurat_v3'
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>, batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:787: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:231: in _highly_variable_genes_seurat_v3
    #x1B[0msquared_batch_counts_sum, batch_counts_sum = clip_square_sum(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

data_batch = Array([[0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=int64)
clip_val = array([ 38.72983346,  38.72983346,  38.72983346,  38.72983346,
        38.72983346,   2.56603309,  38.72983346,  38.72... 38.72983346,   9.25241646,  38.72983346,   6.87568653,
        38.72983346,   1.00092053,  13.19640923,  38.72983346])

    #x1B[0m#x1B[37m@singledispatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mclip_square_sum#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        data_batch: np.ndarray, clip_val: np.ndarray#x1B[90m#x1B[39;49;00m
    ) -> #x1B[96mtuple#x1B[39;49;00m[np.ndarray, np.ndarray] | #x1B[96mtuple#x1B[39;49;00m[DaskArray, DaskArray]:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Clip data_batch by clip_val.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    Parameters#x1B[39;49;00m
    #x1B[33m    ----------#x1B[39;49;00m
    #x1B[33m    data_batch#x1B[39;49;00m
    #x1B[33m        The data to be clipped#x1B[39;49;00m
    #x1B[33m    clip_val#x1B[39;49;00m
    #x1B[33m        Clip by these values (must be broadcastable to the input data)#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    Returns#x1B[39;49;00m
    #x1B[33m    -------#x1B[39;49;00m
    #x1B[33m        The clipeed data#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        batch_counts = data_batch.astype(np.float64).copy()#x1B[90m#x1B[39;49;00m
        clip_val_broad = np.broadcast_to(clip_val, batch_counts.shape)#x1B[90m#x1B[39;49;00m
>       np.putmask(#x1B[90m#x1B[39;49;00m
            batch_counts,#x1B[90m#x1B[39;49;00m
            batch_counts > clip_val_broad,#x1B[90m#x1B[39;49;00m
            clip_val_broad,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE       TypeError: putmask: first argument must be an array#x1B[0m

#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:58: TypeError
tests/test_preprocessing.py::test_filter_cells[max_counts-jax_array]
Stack Traces | 0.059s run time
array_type = <function as_dense_jax_array at 0x7fc02148c930>, max_genes = None
max_counts = 100, min_genes = None, min_counts = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_cells#x1B[39;49;00m(array_type, max_genes, max_counts, min_genes, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:667: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:167: in filter_cells
    #x1B[0madata._inplace_subset_obs(cell_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1241: in _inplace_subset_obs
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False,...False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_preprocessing.py::test_filter_cells[max_genes-jax_array]
Stack Traces | 0.06s run time
array_type = <function as_dense_jax_array at 0x7fc02148c930>, max_genes = 100
max_counts = None, min_genes = None, min_counts = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_cells#x1B[39;49;00m(array_type, max_genes, max_counts, min_genes, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:667: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:167: in filter_cells
    #x1B[0madata._inplace_subset_obs(cell_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1241: in _inplace_subset_obs
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False,...False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_preprocessing.py::test_filter_cells[min_counts-jax_array]
Stack Traces | 0.063s run time
array_type = <function as_dense_jax_array at 0x7fc02148c930>, max_genes = None
max_counts = None, min_genes = None, min_counts = 20

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_cells#x1B[39;49;00m(array_type, max_genes, max_counts, min_genes, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:667: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:167: in filter_cells
    #x1B[0madata._inplace_subset_obs(cell_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1241: in _inplace_subset_obs
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,... True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_preprocessing.py::test_filter_genes[None-None-None-20-jax_array]
Stack Traces | 0.073s run time
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>, max_cells = None
max_counts = None, min_cells = None, min_counts = 20

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            (#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_genes#x1B[39;49;00m(array_type, max_cells, max_counts, min_cells, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:633: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:281: in filter_genes
    #x1B[0madata._inplace_subset_var(gene_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1231: in _inplace_subset_var
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[:, index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,... True,  True,  True,  True,  True, False,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_preprocessing.py::test_filter_genes[None-100-None-None-jax_array]
Stack Traces | 0.08s run time
array_type = <function as_dense_jax_array at 0x7fc02148c930>, max_cells = None
max_counts = 100, min_cells = None, min_counts = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            (#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_genes#x1B[39;49;00m(array_type, max_cells, max_counts, min_cells, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:633: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:281: in filter_genes
    #x1B[0madata._inplace_subset_var(gene_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1231: in _inplace_subset_var
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[:, index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([False,  True, False, False,  True, False, False, False, False,
       False, False, False, False, False, False,...False,  True, False, False, False,  True, False,
       False, False, False, False, False, False,  True, False, False])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_preprocessing.py::test_filter_genes[100-None-None-None-jax_array]
Stack Traces | 0.156s run time
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>, max_cells = 100
max_counts = None, min_cells = None, min_counts = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            (#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_genes#x1B[39;49;00m(array_type, max_cells, max_counts, min_cells, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:633: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:281: in filter_genes
    #x1B[0madata._inplace_subset_var(gene_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1231: in _inplace_subset_var
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[:, index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([False,  True, False, False,  True, False, False, False, False,
       False, False, False, False,  True, False,...False,  True, False, False, False,  True, False,
       False,  True, False, False, False, False,  True, False, False])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_highly_variable_genes.py::test_compare_to_upstream[jax_array-seurat]
Stack Traces | 0.181s run time
request = <FixtureRequest for <Function test_compare_to_upstream[jax_array-seurat]>>
flavor = 'seurat', params = {'min_mean': 0.0125, 'max_mean': 3, 'min_disp': 0.5}
ref_path = PosixPath('.../tests/_scripts/seurat_hvg.csv')
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mref_path#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[96mdict#x1B[39;49;00m(min_mean=#x1B[94m0.0125#x1B[39;49;00m, max_mean=#x1B[94m3#x1B[39;49;00m, min_disp=#x1B[94m0.5#x1B[39;49;00m), FILE, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            ),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[96mdict#x1B[39;49;00m(n_top_genes=#x1B[94m100#x1B[39;49;00m), FILE_CELL_RANGER, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            ),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_compare_to_upstream#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        request: pytest.FixtureRequest,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        params: Any,#x1B[90m#x1B[39;49;00m
        ref_path: Path,#x1B[90m#x1B[39;49;00m
        array_type: Callable,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        hvg_info = pd.read_csv(ref_path)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        pbmc.X = pbmc.raw.X#x1B[90m#x1B[39;49;00m
        pbmc.X = array_type(pbmc.X)#x1B[90m#x1B[39;49;00m
        pbmc.var_names_make_unique()#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_cells(pbmc, min_counts=#x1B[94m1#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:393: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:167: in filter_cells
    #x1B[0madata._inplace_subset_obs(cell_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1241: in _inplace_subset_obs
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,... True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_preprocessing.py::test_filter_cells[min_genes-jax_array]
Stack Traces | 0.224s run time
array_type = <function as_dense_jax_array at 0x7fc02148c930>, max_genes = None
max_counts = None, min_genes = 20, min_counts = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[96mid#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_cells#x1B[39;49;00m(array_type, max_genes, max_counts, min_genes, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_cells(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_genes=max_genes,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_genes=min_genes,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:667: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:167: in filter_cells
    #x1B[0madata._inplace_subset_obs(cell_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1241: in _inplace_subset_obs
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,... True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_preprocessing.py::test_filter_genes[None-None-20-None-jax_array]
Stack Traces | 0.299s run time
array_type = <function as_dense_jax_array at 0x7fc02148c930>, max_cells = None
max_counts = None, min_cells = 20, min_counts = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, ARRAY_TYPES)#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        (#x1B[33m"#x1B[39;49;00m#x1B[33mmax_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmax_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_cells#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mmin_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            (#x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94m100#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
            (#x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94mNone#x1B[39;49;00m, #x1B[94m20#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_filter_genes#x1B[39;49;00m(array_type, max_cells, max_counts, min_cells, min_counts):#x1B[90m#x1B[39;49;00m
        adata = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        adata.X = adata.raw.X#x1B[90m#x1B[39;49;00m
        adata_casted = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_casted.X = array_type(adata_casted.raw.X)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       sc.pp.filter_genes(#x1B[90m#x1B[39;49;00m
            adata_casted,#x1B[90m#x1B[39;49;00m
            max_cells=max_cells,#x1B[90m#x1B[39;49;00m
            max_counts=max_counts,#x1B[90m#x1B[39;49;00m
            min_cells=min_cells,#x1B[90m#x1B[39;49;00m
            min_counts=min_counts,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_preprocessing.py#x1B[0m:633: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_simple.py#x1B[0m:281: in filter_genes
    #x1B[0madata._inplace_subset_var(gene_subset)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1231: in _inplace_subset_var
    #x1B[0madata_subset = #x1B[96mself#x1B[39;49;00m[:, index].copy()#x1B[90m#x1B[39;49;00m
                   ^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1450: in copy
    #x1B[0m#x1B[94mif#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._has_raw_zarr_or_h5_array():#x1B[90m#x1B[39;49;00m
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1445: in _has_raw_zarr_or_h5_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._reduce(predicate, init=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1489: in _reduce
    #x1B[0maccumulate = func(attr, accumulate=accumulate, attr_name=attr_name)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1435: in predicate
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m accumulate #x1B[95mor#x1B[39;49;00m #x1B[96many#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                         ^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1439: in <genexpr>
    #x1B[0m#x1B[94mfor#x1B[39;49;00m v #x1B[95min#x1B[39;49;00m elem.values()#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m<frozen _collections_abc>#x1B[0m:902: in __iter__
    #x1B[0m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[04m#x1B[91m?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_mapping.py#x1B[0m:169: in __getitem__
    #x1B[0m_subset(#x1B[96mself#x1B[39;49;00m.parent_mapping[key], #x1B[96mself#x1B[39;49;00m.subset_idx),#x1B[90m#x1B[39;49;00m
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:391: in _subset
    #x1B[0msubset_idx = _prepare_array_api_idx(a, subset_idx)#x1B[90m#x1B[39;49;00m
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in _prepare_array_api_idx
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                           ^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:361: in <genexpr>
    #x1B[0mmaybe_array_api_idxs = #x1B[96mtuple#x1B[39;49;00m(get_idx(idx) #x1B[94mfor#x1B[39;49;00m idx #x1B[95min#x1B[39;49;00m subset_idx)#x1B[90m#x1B[39;49;00m
                                 ^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/index.py#x1B[0m:353: in get_idx
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m idx.get_for_array(a)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/compat/__init__.py#x1B[0m:90: in get_for_array
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m xp.from_dlpack(existing)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../_src/numpy/lax_numpy.py#x1B[0m:5599: in from_dlpack
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m from_dlpack(x, device=device, copy=copy)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

external_array = array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,... True,  True,  True,  True,  True, False,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True])
device = None, copy = None

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mfrom_dlpack#x1B[39;49;00m(external_array,#x1B[90m#x1B[39;49;00m
                    device: _jax.Device | Sharding | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                    copy: #x1B[96mbool#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
    #x1B[90m  #x1B[39;49;00m#x1B[33m"""Returns a :class:`~jax.Array` representation of a DLPack tensor.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  The returned :class:`~jax.Array` shares memory with ``external_array`` if no#x1B[39;49;00m
    #x1B[33m  device transfer or copy was requested.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Args:#x1B[39;49;00m
    #x1B[33m    external_array: An array object that has ``__dlpack__`` and#x1B[39;49;00m
    #x1B[33m      ``__dlpack_device__`` methods.#x1B[39;49;00m
    #x1B[33m    device: The (optional) :py:class:`Device`, representing the device on which#x1B[39;49;00m
    #x1B[33m      the returned array should be placed. If given, then the result is#x1B[39;49;00m
    #x1B[33m      committed to the device. If unspecified, the resulting array will be#x1B[39;49;00m
    #x1B[33m      unpacked onto the same device it originated from. Setting ``device`` to a#x1B[39;49;00m
    #x1B[33m      device different from the source of ``external_array`` will require a#x1B[39;49;00m
    #x1B[33m      copy, meaning ``copy`` must be set to either ``True`` or ``None``.#x1B[39;49;00m
    #x1B[33m    copy: An (optional) boolean, controlling whether or not a copy is performed.#x1B[39;49;00m
    #x1B[33m      If ``copy=True`` then a copy is always performed, even if unpacked onto#x1B[39;49;00m
    #x1B[33m      the same device. If ``copy=False`` then the copy is never performed and#x1B[39;49;00m
    #x1B[33m      will raise an error if necessary. When ``copy=None`` then a copy may be#x1B[39;49;00m
    #x1B[33m      performed if needed for a device transfer.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Returns:#x1B[39;49;00m
    #x1B[33m    A jax.Array#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m  Note:#x1B[39;49;00m
    #x1B[33m    While JAX arrays are always immutable, dlpack buffers cannot be marked as#x1B[39;49;00m
    #x1B[33m    immutable, and it is possible for processes external to JAX to mutate them#x1B[39;49;00m
    #x1B[33m    in-place. If a jax Array is constructed from a dlpack buffer and the buffer#x1B[39;49;00m
    #x1B[33m    is later modified in-place, it may lead to undefined behavior when using#x1B[39;49;00m
    #x1B[33m    the associated JAX array.#x1B[39;49;00m
    #x1B[33m  """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(device, Sharding):#x1B[90m#x1B[39;49;00m
        device_set = device.device_set#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(device_set) > #x1B[94m1#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mfrom_dlpack can only unpack a dlpack tensor onto a singular device, but #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33ma Sharding with #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mlen#x1B[39;49;00m(device_set)#x1B[33m}#x1B[39;49;00m#x1B[33m devices was provided.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          )#x1B[90m#x1B[39;49;00m
        device, = device_set#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m) #x1B[95mor#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[96mhasattr#x1B[39;49;00m(external_array, #x1B[33m"#x1B[39;49;00m#x1B[33m__dlpack_device__#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mThe array passed to from_dlpack must have __dlpack__ and __dlpack_device__ methods.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      dl_device_type, device_id = external_array.__dlpack_device__()#x1B[90m#x1B[39;49;00m
      #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        dl_device_platform = _DL_DEVICE_TO_PLATFORM[dl_device_type]#x1B[90m#x1B[39;49;00m
      #x1B[94mexcept#x1B[39;49;00m #x1B[96mKeyError#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mraise#x1B[39;49;00m #x1B[96mTypeError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mArray passed to from_dlpack is on unsupported device type #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33m(DLDeviceType: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mdl_device_type#x1B[33m}#x1B[39;49;00m#x1B[33m, array: #x1B[39;49;00m#x1B[33m{#x1B[39;49;00mexternal_array#x1B[33m}#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        ) #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
      backend = xla_bridge.get_backend(dl_device_platform)#x1B[90m#x1B[39;49;00m
      dlpack_device = backend.device_from_local_hardware_id(device_id)#x1B[90m#x1B[39;49;00m
      _check_device(device, dlpack_device, copy)#x1B[90m#x1B[39;49;00m
      #x1B[94mif#x1B[39;49;00m _is_tensorflow_tensor(external_array):#x1B[90m#x1B[39;49;00m
        #x1B[90m# TensorFlow does not support stream=.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melif#x1B[39;49;00m dl_device_type #x1B[95min#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLCUDAHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLROCMHost,#x1B[90m#x1B[39;49;00m
          DLDeviceType.kDLTPUHost,#x1B[90m#x1B[39;49;00m
      ):#x1B[90m#x1B[39;49;00m
        #x1B[90m# Some producers (e.g. torch.Tensor with is_pinned()) route pinned tensors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# through their CPU __dlpack__, which rejects a non-None stream argument.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
      #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        #x1B[94mtry#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
          stream = dlpack_device.get_stream_for_external_ready_events()#x1B[90m#x1B[39;49;00m
        #x1B[94mexcept#x1B[39;49;00m _jax.JaxRuntimeError #x1B[94mas#x1B[39;49;00m err:#x1B[90m#x1B[39;49;00m
          #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mUNIMPLEMENTED#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m #x1B[96mstr#x1B[39;49;00m(err):#x1B[90m#x1B[39;49;00m
            stream = #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
          #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>     dlpack = external_array.__dlpack__(stream=stream)#x1B[90m#x1B[39;49;00m
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE     BufferError: Cannot export readonly array since signalling readonly is unsupported by DLPack (supported by newer DLPack version).#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../jax/_src/dlpack.py#x1B[0m:277: BufferError
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-jax_array-seurat_v3_paper]
Stack Traces | 0.341s run time
subtests = <_pytest.subtests.Subtests object at 0x7f9c1c3e69f0>
flavor = 'seurat_v3_paper'
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>, batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:787: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:231: in _highly_variable_genes_seurat_v3
    #x1B[0msquared_batch_counts_sum, batch_counts_sum = clip_square_sum(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

data_batch = Array([[0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=int64)
clip_val = array([ 38.72983346,  38.72983346,  38.72983346,  38.72983346,
        38.72983346,   2.56603309,  38.72983346,  38.72... 38.72983346,   9.25241646,  38.72983346,   6.87568653,
        38.72983346,   1.00092053,  13.19640923,  38.72983346])

    #x1B[0m#x1B[37m@singledispatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mclip_square_sum#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        data_batch: np.ndarray, clip_val: np.ndarray#x1B[90m#x1B[39;49;00m
    ) -> #x1B[96mtuple#x1B[39;49;00m[np.ndarray, np.ndarray] | #x1B[96mtuple#x1B[39;49;00m[DaskArray, DaskArray]:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Clip data_batch by clip_val.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    Parameters#x1B[39;49;00m
    #x1B[33m    ----------#x1B[39;49;00m
    #x1B[33m    data_batch#x1B[39;49;00m
    #x1B[33m        The data to be clipped#x1B[39;49;00m
    #x1B[33m    clip_val#x1B[39;49;00m
    #x1B[33m        Clip by these values (must be broadcastable to the input data)#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    Returns#x1B[39;49;00m
    #x1B[33m    -------#x1B[39;49;00m
    #x1B[33m        The clipeed data#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        batch_counts = data_batch.astype(np.float64).copy()#x1B[90m#x1B[39;49;00m
        clip_val_broad = np.broadcast_to(clip_val, batch_counts.shape)#x1B[90m#x1B[39;49;00m
>       np.putmask(#x1B[90m#x1B[39;49;00m
            batch_counts,#x1B[90m#x1B[39;49;00m
            batch_counts > clip_val_broad,#x1B[90m#x1B[39;49;00m
            clip_val_broad,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE       TypeError: putmask: first argument must be an array#x1B[0m

#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:58: TypeError
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[batch-jax_array-seurat_v3]
Stack Traces | 0.421s run time
subtests = <_pytest.subtests.Subtests object at 0x7f9c0cee8e20>
flavor = 'seurat_v3'
array_type = <function as_dense_jax_array at 0x7f9c4af9be20>
batch_key = 'batch'

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:787: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:185: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = aggregate(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/get/_aggregated.py#x1B[0m:386: in aggregate
    #x1B[0mlayers = _aggregate(data, by=categorical, func=func, mask=mask, dof=dof)#x1B[90m#x1B[39;49;00m
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.7-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

data = Array([[0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 1, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=int64)
by = ['b', 'b', 'b', 'a', 'a', ..., 'a', 'a', 'b', 'b', 'a']
Length: 1500
Categories (2, str): ['a', 'b']
func = ['mean', 'var'], mask = None, dof = 1

    #x1B[0m#x1B[37m@singledispatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_aggregate#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        data,#x1B[90m#x1B[39;49;00m
        by: pd.Categorical,#x1B[90m#x1B[39;49;00m
        func: AggType | Iterable[AggType],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        mask: NDArray[np.bool] | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        dof: #x1B[96mint#x1B[39;49;00m = #x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[96mdict#x1B[39;49;00m[AggType, np.ndarray | DaskArray]:#x1B[90m#x1B[39;49;00m
        msg = #x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mData type #x1B[39;49;00m#x1B[33m{#x1B[39;49;00m#x1B[96mtype#x1B[39;49;00m(data)#x1B[33m}#x1B[39;49;00m#x1B[33m not supported for aggregation#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>       #x1B[94mraise#x1B[39;49;00m #x1B[96mNotImplementedError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE       NotImplementedError: Data type <class 'jaxlib._jax.ArrayImpl'> not supported for aggregation#x1B[0m

#x1B[1m#x1B[.../scanpy/get/_aggregated.py#x1B[0m:417: NotImplementedError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@flying-sheep
flying-sheep self-requested a review June 25, 2026 14:58

@flying-sheep flying-sheep left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, please remember the comments from the fast-array-utils PR, e.g. we agreed to handle singledispatch functions like this: https://github.com/scverse/fast-array-utils/blob/febaf245ecd6da849c2331638219f649935d5a21/src/fast_array_utils/stats/_power.py#L38-L39

We also need tests. There’s MAP_ARRAY_TYPES which should gain an entry, which will make many many tests run with the type you add. We can discuss how to best exclude certain tests, for starters you can just add it and make some of the tests fail – that’ll show you where things aren’t working yet (and might or might not be fixed in this PR)

Please also add a release note (hatch run towncrier:create 4179.feat.md)

@flying-sheep flying-sheep changed the title Add Array API support via array-api-compat feat: add Array API support via array-api-compat Jul 17, 2026
Comment thread src/scanpy/_utils/__init__.py Outdated
Comment thread src/scanpy/_utils/__init__.py Outdated
Comment thread src/scanpy/_utils/__init__.py Outdated
Comment thread src/scanpy/metrics/_common.py Outdated
Comment thread src/scanpy/preprocessing/_highly_variable_genes.py Outdated
Comment thread src/scanpy/preprocessing/_normalization.py Outdated
Comment thread src/scanpy/preprocessing/_scale.py Outdated
Comment thread src/scanpy/preprocessing/_simple.py Outdated
Comment thread src/scanpy/_compat.py Outdated
Comment thread src/testing/scanpy/_pytest/__init__.py

@flying-sheep flying-sheep left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Just nitpicks left in the code that’s there.

One big change we should do is updating the array type metadata so it lists Array API support.

The docs currently have one central table and each function has its own little info box.

Since you know what’s going to be supported, you should update the metadata by adding an aa tag and filling out the support here (so far, np means numpy, sp means scipy sparse, da means dask, da[...] means “... in dask”, and sp[csc] means “scipy sparse with csc format”):

scanpy/docs/conf.py

Lines 178 to 210 in fc0b419

array_support: dict[str, tuple[list[str], list[str]]] = {
"experimental.pp.highly_variable_genes": (["np", "sp"], []),
"get.aggregate": (["np", "sp", "da"], []),
"pp.calculate_qc_metrics": (["np", "sp", "da"], []),
"pp.combat": (["np"], []),
"pp.downsample_counts": (["np", "sp[csr]"], []),
"pp.filter_cells": (["np", "sp", "da"], []),
"pp.filter_genes": (["np", "sp", "da"], []),
"pp.harmony_integrate": (["np"], []),
"pp.highly_variable_genes": (["np", "sp", "da"], ["da[sp[csc]]"]),
"pp.log1p": (["np", "sp", "da"], []),
"pp.neighbors": (["np", "sp"], []),
"pp.normalize_total": (["np", "sp[csr]", "da"], []),
"pp.pca": (["np", "sp", "da"], ["da[sp[csc]]"]),
"pp.regress_out": (["np"], []),
"pp.sample": (["np", "sp", "da"], []),
"pp.scale": (["np", "sp", "da"], []),
"pp.scrublet": (["np", "sp"], []),
"pp.scrublet_simulate_doublets": (["np", "sp"], []),
"tl.dendrogram": (["np", "sp"], []),
"tl.diffmap": (["np", "sp"], []),
"tl.dpt": (["np", "sp"], []),
"tl.draw_graph": (["np", "sp"], []), # only uses graph in obsp
"tl.embedding_density": (["np"], []),
"tl.ingest": (["np", "sp"], []),
"tl.leiden": (["np", "sp"], []), # only uses graph in obsp
"tl.louvain": (["np", "sp"], []), # only uses graph in obsp
"tl.paga": (["np", "sp"], []),
"tl.rank_genes_groups": (["np", "sp"], []),
"tl.score_genes": (["np", "sp"], []),
"tl.tsne": (["np", "sp"], []),
"tl.umap": (["np", "sp"], []),
}

If you want, you can also update the Sphinx code, but you don’t need to learn how to do that if you don’t want to. I’ll happily do that myself.

Comment thread src/scanpy/_compat.py Outdated
Comment thread pyproject.toml Outdated
Comment thread tests/test_pca.py
svd_solvers = {"auto", "full", "arpack", "randomized", "covariance_eigh"}
case (helpers.asarray, False):
case (helpers.asarray | helpers.as_dense_jax_array, True):
svd_solvers = {"auto", "full", "arpack", "randomized"} | SKLEARN_ADDITIONAL

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn’t exist and breaks the tests

@flying-sheep flying-sheep Aug 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you resolve this? SKLEARN_ADDITIONAL still doesn’t exist and breaks the tests.

Comment on lines +884 to +886
# rank_genes_groups uses numba kernels internally, so need convert at entry.
if isinstance(adata.X, HasArrayNamespace) and not isinstance(adata.X, np.ndarray):
adata.X = np.asarray(adata.X)

@flying-sheep flying-sheep Aug 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn’t the right approach, as it modifies an object the user passed. Why not do this in _RankGenes.__init__?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants