Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c567bc2
feat(netcdf): make the container a mapping, and add the xarray-compat…
MAfarrag Sep 14, 2026
a177510
test(netcdf): pin the mapping protocol, the aliases and the cheap int…
MAfarrag Sep 14, 2026
1b06c9e
test(netcdf): cover what the new members answer on a variable subset
MAfarrag Sep 14, 2026
adc101f
docs(netcdf): make the new members' examples show values instead of a…
MAfarrag Sep 14, 2026
b399452
fix(netcdf): annotate variables as the lazy mapping it actually returns
MAfarrag Sep 14, 2026
d1659ce
fix(netcdf): stop keys() handing out the list the container runs on
MAfarrag Sep 15, 2026
07b6350
feat(netcdf)!: make data_vars the variables mapping, as xarray's is
MAfarrag Sep 15, 2026
307946e
fix(netcdf): size a variable with no nameable dtype as zero, not a Ty…
MAfarrag Sep 15, 2026
409646f
fix(netcdf): make dtypes, nbytes and info survive a classic container
MAfarrag Sep 15, 2026
e3c2716
docs(netcdf): record that a container now duck-types as a sequence
MAfarrag Sep 15, 2026
12058ce
test(netcdf): count the reads GDAL really makes, and say what they are
MAfarrag Sep 15, 2026
ea85851
test(netcdf): pin hand-checked answers behind the alias comparisons
MAfarrag Sep 15, 2026
e06f657
docs(netcdf): state where each alias diverges from the xarray member …
MAfarrag Sep 15, 2026
d8fa569
docs(netcdf): index the new members, and stop the page drifting again
MAfarrag Sep 15, 2026
8407773
refactor(netcdf): tighten the new members' types and trim info's attr…
MAfarrag Sep 15, 2026
5d076bf
test(netcdf): cover the conditions line coverage cannot see
MAfarrag Sep 15, 2026
5b58350
docs(netcdf): correct six false claims in the new members' docstrings
MAfarrag Sep 15, 2026
a74e16d
fix(netcdf): refuse array coercion instead of answering nan for a var…
MAfarrag Sep 15, 2026
86aaa8c
fix(netcdf): stop _summarised eating backslashes, and refuse writes i…
MAfarrag Sep 15, 2026
b8a7508
docs(netcdf): note that xarray is deprecating Dataset.dims as a mapping
MAfarrag Sep 15, 2026
3dad26d
fix(netcdf): make a swallowed refusal audible, and agree on what "the…
MAfarrag Sep 15, 2026
6364ecc
fix(netcdf): close the other six doors into the variables cache
MAfarrag Sep 15, 2026
29e238b
docs(netcdf): correct three claims the last round of fixes made false
MAfarrag Sep 15, 2026
05890a1
test(netcdf): one call per raises and warns block
MAfarrag Sep 15, 2026
ebf9927
docs(netcdf): say that a container's array coercion changed from a va…
MAfarrag Sep 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,30 @@ replace the georeference wholesale.

### unreleased

**A container now duck-types as a sequence, because it gained `__iter__` and `__len__`.** `NetCDF` had
neither dunder before, so every `isinstance(x, Iterable)` test answered `False` for one. That flipped:

| expression | before | now |
|---|---|---|
| `isinstance(nc, collections.abc.Iterable / Sized / Container)` | `False` | `True` |
| `isinstance(nc, collections.abc.Mapping / Sequence)` | `False` | `False`, unchanged |

- The case to check is a helper of your own that accepts "anything iterable". It used to reject a container
outright and now quietly receives a list of name strings, so a mistake fails later and less clearly than it
used to. Gate on `isinstance(x, NetCDF)` first if that matters.
- **Array coercion now raises, where a container used to answer uselessly.** `np.asarray(nc)` returned a 0-d
object array wrapping the container; it now raises `TypeError` pointing at `nc["name"].read_array()`. That is
a hard change, but the old value was a box around the object rather than any of its data, so nothing could
have been computing with it.

The refusal exists for the *variable* case, where leaving the coercion alone would have been worse than
useless: iterating a variable yields nothing, so `np.mean(nc["t2m"])` would have answered `nan` for a cube of
real values. `origin/main` raised there, and so does this — only the exception type differs.
- `np.array([nc], dtype=object)` still boxes the dataset and is still `(1,)`: that request reads nothing and
fabricates nothing, so it is the one `__array__` honours.
- `bool(nc)` is unaffected: `Dataset.__bool__` still refuses, and takes precedence over `__len__`. Ask
`len(nc) == 0` whether a container is empty.

**`to_xarray()` decodes the CF time axis, so the coordinate is `datetime64[ns]` rather than `float64`.**
Hard change, silent for the read side — nothing raises and nothing warns when the axis decodes. The bridge
exists to hand you to xarray, and `resample`, `.dt` and `groupby("time.<component>")` all raised on the numeric
Expand Down
64 changes: 48 additions & 16 deletions docs/reference/netcdf/public-api.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# `NetCDF` — public API

A one-line map of every public member the `NetCDF` class itself defines — 65 in all: 38 methods, 20 properties,
6 classmethods and 1 staticmethod. For the full signatures, arguments and examples, see the rendered
A one-line map of every public member the `NetCDF` class itself defines — 77 in all: 43 methods, 27 properties,
6 classmethods and 1 staticmethod, plus the four mapping dunders (`__getitem__`, `__contains__`, `__iter__`,
`__len__`). For the full signatures, arguments and examples, see the rendered
[NetCDF Class](index.md) reference; this page is the index you scan to find the member you want.

`NetCDF` extends `Dataset`, so it also inherits a further 134 public members it does not redefine — band
Expand Down Expand Up @@ -30,20 +31,51 @@ Two object shapes share this class, and several members behave differently acros

## Variables, dimensions and groups

| Member | What it does |
|--------------------------|---------------------------------------------------------------------------|
| `variable_names` | Names of the data variables, excluding dimension coordinate arrays. |
| `variables` | Lazy `{name: subset}` mapping of every data variable. |
| `get_variable()` | Extracts one variable as a classic-raster `NetCDF` (a Variable). |
| `get_variable_names()` | Deprecated alias for the `variable_names` property. |
| `dimension_names` | Names of all dimensions, in storage order. |
| `dimension_sizes` | `{name: size}` for every dimension, read from the multidimensional group. |
| `get_dimension_values()` | Stored coordinates of any dimension — `level`, `depth`, `member`, `time`. |
| `group_names` | Names of the sub-groups in the root group. |
| `get_group()` | Opens a netCDF-4 sub-group as its own Container, without copying data. |
| `is_subset` | Whether this object is a single-variable subset rather than a Container. |
| `is_md_array` | Whether the dataset was opened in multidimensional mode. |
| `file_name` | The file path, with any `NETCDF:"path":var` prefix stripped. |
| Member | What it does |
|--------------------------|---------------------------------------------------------------------------------|
| `variable_names` | Names of the data variables, excluding dimension coordinate arrays. |
| `variables` | Lazy `{name: subset}` mapping of every data variable. |
| `get_variable()` | Extracts one variable as a classic-raster `NetCDF` (a Variable). |
| `get_variable_names()` | Deprecated alias for the `variable_names` property. |
| `nc[name]` | The variable called `name`; `KeyError` where `get_variable` gives `ValueError`. |
| `name in nc` | Whether `name` is one of the data variables. |
| `iter(nc)` / `len(nc)` | The data-variable names, and how many there are. |
| `get()` | The variable, or a default when the container has no such name. |
| `keys()` | The data-variable names, as a fresh list. |
| `values()` | Every variable, loading each. |
| `items()` | `(name, variable)` for every variable, loading each. |
| `dimension_names` | Names of all dimensions, in storage order. |
| `dimension_sizes` | `{name: size}` for every dimension, read from the multidimensional group. |
| `get_dimension_values()` | Stored coordinates of any dimension — `level`, `depth`, `member`, `time`. |
| `group_names` | Names of the sub-groups in the root group. |
| `get_group()` | Opens a netCDF-4 sub-group as its own Container, without copying data. |
| `is_subset` | Whether this object is a single-variable subset rather than a Container. |
| `is_md_array` | Whether the dataset was opened in multidimensional mode. |
| `file_name` | The file path, with any `NETCDF:"path":var` prefix stripped. |

## xarray-compatible spellings

Aliases so habits from xarray transfer without renaming anything. Each names its canonical member, and each
docstring states where it diverges from the xarray member it echoes.

| Member | What it does |
|-------------|----------------------------------------------------------------------------------------|
| `data_vars` | `variables` under xarray's name — a mapping, so `nc.data_vars["t2m"]` works. |
| `dims` | `{name: length}` — **not** `dimension_names`, a list. `sizes` is the durable spelling. |
| `sizes` | The same mapping as `dims`; xarray is turning its own `dims` into a set of names. |
| `attrs` | `global_attributes` under xarray's name. |
| `coords` | `{name: stored coordinate}` for every indexed dimension, from `get_dimension_values`. |

## Cheap introspection

Metadata only: no data variable's array is read, though opening a variable does read its coordinate axes.
A variable with no raster plane is the exception — see each member's docstring.

| Member | What it does |
|----------|-----------------------------------------------------------------------------------|
| `dtypes` | `{name: dtype}` for every data variable, from the band description. |
| `nbytes` | Total size of the data variables, computed from shape and dtype rather than read. |
| `info()` | Prints an `ncdump -h`-shaped summary to a buffer, or to `sys.stdout`. |

## Coordinates and time

Expand Down
Loading