Skip to content

Dataset used in ds in ... statements have un-intuitive behaviour #11209

@VeckoTheGecko

Description

@VeckoTheGecko

What happened?

I've been writing type guards like the following

def some_calculation(ds: xr.Dataset, calculation_type: Literal["polar", "cartesian"]) -> xr.Dataset:
    if calculation_type not in ("polar", "cartesian"):
        raise ValueError(f"Invalid calculation_type. Expected 'polar' or 'cartesian'. Got {type=!r}")
    ...
    return ds

but if calculation_type is an Xarray dataset, a lot of the time it bypasses this check.

I think this is somewhat related to #6124 (i.e., it looks to the implementation of __bool__ somewhere), though I think this issue is more clear cut what the output should be.

What did you expect to happen?

I expected ds in ("polar", "cartesian") to be False

Minimal Complete Verifiable Example

# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "xarray[complete]@git+https://github.com/pydata/xarray.git@main",
# ]
# ///
#
# This script automatically imports the development branch of xarray to check for issues.
# Please delete this header if you have _not_ tested this script with `uv run`!

import xarray as xr
xr.show_versions()

import numpy as np

from typing import Literal

def some_calculation(ds: xr.Dataset, calculation_type: Literal["polar", "cartesian"]) -> xr.Dataset:
    if calculation_type not in ("polar", "cartesian"):
        raise ValueError(f"Invalid calculation_type. Expected 'polar' or 'cartesian'. Got {type=!r}")
    ...
    return ds

ds = xr.Dataset({"a": (("dim1",'dim2'), np.arange(20).reshape(4,5))})

# Expected usecase
some_calculation(ds, "polar")

# Invalid usecase
try:
    some_calculation(ds, "invalid-option")
except ValueError: # expected behaviour
    pass

# Invalid usecases (but using xarray dataset as input)
some_calculation(ds, ds)
# 'passes' because
assert ds in ("polar", "cartesian")
assert False, "Above expressions should not have passed!"

Steps to reproduce

No response

MVCE confirmation

  • Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray.
  • Complete example — the example is self-contained, including all data and the text of any traceback.
  • Verifiable example — the example copy & pastes into an IPython prompt or Binder notebook, returning the result.
  • New issue — a search of GitHub Issues suggests this is not a duplicate.
  • Recent environment — the issue occurs with the latest version of xarray and its dependencies.

Relevant log output

Anything else we need to know?

No response

Environment

Details

INSTALLED VERSIONS

commit: None
python: 3.14.3 | packaged by conda-forge | (main, Feb 9 2026, 22:09:14) [Clang 20.1.8 ]
python-bits: 64
OS: Darwin
OS-release: 24.6.0
machine: arm64
processor: arm
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: ('en_US', 'UTF-8')
libhdf5: None
libnetcdf: None

xarray: 2026.2.0
pandas: 3.0.1
numpy: 2.4.2
scipy: None
netCDF4: None
pydap: None
h5netcdf: None
h5py: None
zarr: None
cftime: None
nc_time_axis: None
iris: None
bottleneck: None
dask: None
distributed: None
matplotlib: None
cartopy: None
seaborn: None
numbagg: None
fsspec: None
cupy: None
pint: None
sparse: None
flox: None
numpy_groupies: None
setuptools: None
pip: None
conda: None
pytest: None
mypy: None
IPython: None
sphinx: None

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions