Skip to content

Conversation

@flying-sheep
Copy link
Member

@flying-sheep flying-sheep commented Jan 8, 2026

User API design

  1. create AdPath instances by descending into a central accessor constant A:
    (A[:, :], lambda ad: ad.X),
    (A[:, "gene-3"], lambda ad: ad[:, "gene-3"].X.flatten()),
    (A["cell-5", :], lambda ad: ad["cell-5"].X.flatten()),
    (A.obs["type"], lambda ad: ad.obs["type"]),
    (A.obs.index, lambda ad: ad.obs.index.values),
    (A.layers["a"][:, :], lambda ad: ad.layers["a"].copy().toarray()),
    (
    A.layers["a"][:, "gene-18"],
    lambda ad: ad[:, "gene-18"].layers["a"].copy().toarray().flatten(),
    ),
    (
    A.layers["a"]["cell-77", :],
    lambda ad: ad["cell-77"].layers["a"].copy().toarray().flatten(),
    ),
    (A.obsm["umap"][0], lambda ad: ad.obsm["umap"][:, 0]),
    (A.obsm["umap"][1], lambda ad: ad.obsm["umap"][:, 1]),
    (A.varp["cons"]["gene-46", :], lambda ad: ad.varp["cons"][46, :].toarray()),
    (A.varp["cons"][:, "gene-46"], lambda ad: ad.varp["cons"][:, 46].toarray()),
  2. Inspect AdPath instance, e.g. to figure out which axes the resulting vector spans:
    pytest.param(A.obsm["c"][:, 0], {"obs"}, id="obsm"),
    pytest.param(A.varp["d"][:, :], ("var", "var"), id="varp"),
    pytest.param(A.varp["d"][:, "c2"], {"var"}, id="varp-col"),
    ],
    )
    def test_axes(ad_path: AdPath, axes: Collection[Literal["obs", "var"]]) -> None:
    assert ad_path.axes == axes
  3. Call AdPath instance to extract a vector (see 1. for examples)

subclassing

… is a direct goal of this, as people should be able to use AdPath subclasses. This means that

  1. the AdPath API is minimal and inspection can be done through .acc (could be even more minimal by just putting it all into a container?):
    acc: VecAcc[Self, I]
    idx: I
    @cached_property
    def axes(self) -> Axes:
  2. It’s trivial to create a new AdAcc constant that produces your own AdPath subclass:
    A = AdAcc(path_class=AdPath)
  3. The data flow is easy to understand:
    1. User uses VecAcc.__getitem__ to get an AdPath or a list of them. In that process,
      1. __getitem__ calls process_idx which verifies and simplifies the index
      2. axes, __repr__, and idx_repr get called too to validate things work
    2. The public API of AdPath can be used, which basically just delegates to VecAcc’s axes, __repr__, idx_repr, and __call__

So in the end everything except for __call__ is validated, i.e. VecAcc.__getitem__ raises exceptions on misuse

class VecAcc[P: AdPath[I], I](abc.ABC): # type: ignore
path_class: type[P]
def process_idx(self, idx: Any, /) -> I:
self.axes(idx)
return idx
def __getitem__(self, idx: Any, /) -> P:
idx = self.process_idx(idx)
return self.path_class(self, idx) # type: ignore
@abc.abstractmethod
def axes(self, idx: I, /) -> Axes: ...
@abc.abstractmethod
def __repr__(self, /) -> str: ...
@abc.abstractmethod
def idx_repr(self, idx: I, /) -> str: ...
@abc.abstractmethod
def __call__(self, adata: AnnData, idx: I, /) -> Vector: ...

TODO:

  • serialization
  • docs (especially data flow)
    • nomenclature: “vector” vs “array”, “accessor”, “vector accessor”, “reference”, “path”, … get it straight!
      Especially since we already call these accessors! Instance namespaces (adata.custom) #1869
  • Array types: fix typing and test with all array types we support
  • (maybe) runtime autocompletion (__dir__)

@codecov
Copy link

codecov bot commented Jan 8, 2026

❌ 12 Tests Failed:

Tests completed Failed Passed Skipped
6719 12 6707 2079
View the top 3 failed test(s) by shortest run time
tests.test_accessors::test_get_values[A.layers['a']['cell-77', :]]
Stack Traces | 0.002s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([2, 1, 3, 5, 0, 4, 2, 4, 5, 4, 2, 3, 5, 1, 3, 3, 0, 0, 5, 3, 1, 3,
       0, 1, 5, 3, 2, 3, 3, 5, 5, 3, 4, 0, 4, 5, 1, 0, 4, 5, 0, 2, 3, 2,
       1, 4, 5, 3, 4, 5])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.obs.index]
Stack Traces | 0.002s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([1, 1, 3, 0, 3, 0, 4, 1, 1, 5, 4, 1, 3, 0, 2, 3, 5, 5, 4, 1, 0, 1,
       1, 1, 3, 4, 1, 0, 1, 1, 2, 1, 1, 1, 2, 5, 1, 3, 5, 0, 1, 5, 0, 2,
       5, 1, 5, 5, 0, 0])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.obsm['umap'][:, 0]]
Stack Traces | 0.002s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([1, 0, 5, 4, 1, 2, 3, 2, 0, 4, 1, 4, 5, 2, 1, 5, 3, 2, 2, 0, 2, 1,
       5, 2, 2, 3, 1, 2, 0, 3, 4, 1, 5, 2, 4, 0, 1, 4, 5, 0, 2, 2, 1, 5,
       4, 0, 0, 2, 5, 2])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.varp['cons'][:, 'gene-46']]
Stack Traces | 0.002s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([1, 0, 0, 1, 4, 2, 5, 3, 3, 1, 0, 4, 5, 4, 3, 5, 0, 5, 3, 5, 2, 5,
       4, 1, 3, 2, 5, 3, 1, 4, 1, 1, 3, 2, 1, 1, 4, 0, 4, 4, 0, 2, 0, 4,
       2, 1, 5, 2, 5, 1])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.layers['a'][:, 'gene-18']]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([0, 1, 0, 3, 5, 3, 3, 2, 0, 1, 2, 4, 0, 4, 1, 5, 1, 2, 0, 0, 0, 5,
       3, 0, 0, 5, 0, 2, 0, 5, 0, 5, 1, 2, 3, 1, 4, 3, 4, 2, 2, 5, 5, 4,
       0, 4, 3, 0, 4, 2])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.layers['a'][:, :]]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([0, 5, 5, 3, 0, 2, 1, 2, 0, 3, 2, 3, 4, 0, 4, 3, 5, 2, 4, 5, 0, 1,
       5, 0, 4, 2, 4, 5, 3, 4, 4, 0, 1, 3, 1, 0, 2, 1, 5, 4, 2, 1, 0, 5,
       2, 1, 1, 3, 1, 1])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.obs['type']]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([0, 2, 4, 0, 0, 2, 2, 4, 4, 4, 3, 1, 1, 2, 2, 5, 2, 5, 1, 1, 5, 1,
       5, 4, 1, 1, 5, 5, 0, 4, 4, 2, 4, 4, 0, 3, 0, 0, 4, 3, 3, 1, 3, 2,
       2, 5, 3, 4, 1, 5])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.obsm['umap'][:, 1]]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([5, 2, 4, 2, 5, 1, 5, 0, 1, 1, 2, 4, 5, 2, 0, 0, 0, 1, 2, 2, 2, 3,
       1, 3, 4, 1, 5, 0, 3, 3, 3, 3, 4, 1, 3, 1, 3, 0, 3, 1, 0, 4, 3, 3,
       3, 1, 0, 2, 3, 3])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A.varp['cons']['gene-46', :]]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([4, 5, 3, 3, 2, 2, 5, 1, 3, 4, 1, 5, 0, 3, 4, 0, 3, 3, 2, 3, 2, 3,
       3, 2, 5, 5, 5, 2, 0, 4, 1, 2, 0, 1, 0, 3, 3, 5, 5, 3, 3, 1, 1, 5,
       3, 0, 1, 4, 2, 3])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A['cell-5', :]]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([3, 0, 2, 4, 2, 5, 4, 4, 2, 5, 1, 1, 5, 2, 3, 0, 5, 4, 1, 5, 1, 4,
       0, 0, 2, 5, 0, 5, 4, 0, 1, 5, 1, 4, 2, 4, 0, 4, 2, 4, 4, 3, 1, 2,
       5, 3, 1, 1, 3, 0])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A[:, 'gene-3']]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([1, 5, 2, 3, 1, 4, 3, 5, 0, 5, 4, 4, 0, 0, 1, 3, 5, 3, 3, 2, 0, 3,
       4, 4, 3, 5, 0, 1, 4, 2, 3, 0, 3, 3, 3, 0, 3, 3, 0, 3, 4, 3, 4, 2,
       0, 3, 2, 3, 4, 1])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning
tests.test_accessors::test_get_values[A[:, :]]
Stack Traces | 0.003s run time
#x1B[0m#x1B[37m@pytest#x1B[39;49;00m.fixture#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92madata#x1B[39;49;00m() -> AnnData:#x1B[90m#x1B[39;49;00m
        gen = np.random.default_rng()#x1B[90m#x1B[39;49;00m
        x = gen.random((#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m), dtype=np.float32)#x1B[90m#x1B[39;49;00m
        layers = #x1B[96mdict#x1B[39;49;00m(a=sp.random(#x1B[94m100#x1B[39;49;00m, #x1B[94m50#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        obs = pd.DataFrame(#x1B[90m#x1B[39;49;00m
            #x1B[96mdict#x1B[39;49;00m(#x1B[96mtype#x1B[39;49;00m=gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m, size=#x1B[94m100#x1B[39;49;00m)),#x1B[90m#x1B[39;49;00m
            index=#x1B[33m"#x1B[39;49;00m#x1B[33mcell-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m + pd.array(#x1B[96mrange#x1B[39;49;00m(#x1B[94m100#x1B[39;49;00m)).astype(#x1B[96mstr#x1B[39;49;00m),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       var_grp = pd.Categorical(#x1B[90m#x1B[39;49;00m
            gen.integers(#x1B[94m0#x1B[39;49;00m, #x1B[94m6#x1B[39;49;00m, size=#x1B[94m50#x1B[39;49;00m), categories=#x1B[96mlist#x1B[39;49;00m(ascii_lowercase[:#x1B[94m5#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_accessors.py#x1B[0m:104: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:504: in __init__
    #x1B[0mcodes = _get_codes_for_values(values, dtype.categories)#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

values = array([4, 4, 2, 1, 5, 5, 2, 1, 0, 3, 5, 5, 0, 0, 3, 5, 1, 5, 1, 2, 0, 3,
       2, 1, 2, 3, 5, 5, 3, 0, 4, 5, 3, 5, 1, 3, 4, 1, 0, 2, 0, 1, 4, 3,
       2, 1, 0, 0, 2, 3])
categories = Index(['a', 'b', 'c', 'd', 'e'], dtype='str')

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_get_codes_for_values#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        values: Index | Series | ExtensionArray | np.ndarray,#x1B[90m#x1B[39;49;00m
        categories: Index,#x1B[90m#x1B[39;49;00m
    ) -> np.ndarray:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    utility routine to turn values into codes given the specified categories#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    If `values` is known to be a Categorical, use recode_for_categories instead.#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        codes = categories.get_indexer_for(values)#x1B[90m#x1B[39;49;00m
        wrong = (codes == -#x1B[94m1#x1B[39;49;00m) & ~isna(values)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m wrong.any():#x1B[90m#x1B[39;49;00m
>           warnings.warn(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mConstructing a Categorical with a dtype and values containing #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnon-null entries not in that dtype#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms categories is deprecated #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mand will raise in a future version.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                Pandas4Warning,#x1B[90m#x1B[39;49;00m
                stacklevel=find_stack_level(),#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           pandas.errors.Pandas4Warning: Constructing a Categorical with a dtype and values containing non-null entries not in that dtype's categories is deprecated and will raise in a future version.#x1B[0m

#x1B[1m#x1B[31m../../../..../anndata/88DSKUwu/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:3045: Pandas4Warning

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 added this to the 0.13.0 milestone Jan 15, 2026
Copy link
Contributor

@ilan-gold ilan-gold left a comment

Choose a reason for hiding this comment

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

Mentioned on slack, but I think the landing page needs to make clear A.obsm["pca"](adata) is possible!

I have to run now but I have a broader question - is there a desire to do some form of validation as well? Like A.obs["x"].validate(adata) or similar. And relatedly asserting types might be in-scope like A.obsm["X_pca"].is(np.ndarray).validate(adata) or similar

Super nice! Very exciting


@dataclass(frozen=True)
class RefAcc[R: AdRef[I], I](abc.ABC): # type: ignore
"""Abstract base class for reference accessors.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a terminology page where you explain these concepts (either centralized on acc or within each class) would be good explaining full name i.e., "reference" for Ref and its meanings (and hten how they are composed)

object.__setattr__(self, "obsp", GraphMapAcc("obs", ref_class=self.ref_class))
object.__setattr__(self, "varp", GraphMapAcc("var", ref_class=self.ref_class))

def to_json(self, ref: R) -> list[str | int | None]:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why have a to_json method? Genuinely wondering about the use-case here.

You can refer to columns or the index in the way you would access them
in a :class:`~pandas.DataFrame`:

>>> from anndata.acc import A
Copy link
Contributor

Choose a reason for hiding this comment

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

I would add a line

Suggested change
>>> from anndata.acc import A
>>> from anndata.acc import A, MetaAcc
>>> isinstance(A.obs, MetaAcc)

I think it's implicit in the description, but I would find this helpful (in all of the classes)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reference paths / accessors

3 participants