From 93122d8e2ff2cf7515eb50e780c3171d72ac73f1 Mon Sep 17 00:00:00 2001 From: Brendan Collins Date: Fri, 6 Nov 2026 10:15:28 -0500 Subject: [PATCH 1/3] Document the 1.x semver and deprecation policy, add the 0.x to 1.0 migration page and accessor reference (#3760) --- docs/source/reference/accessor.rst | 36 +++++++++ .../reference/geotiff_release_contract.md | 7 +- docs/source/reference/index.rst | 1 + docs/source/user_guide/index.rst | 1 + docs/source/user_guide/migration_1_0.rst | 77 +++++++++++++++++++ docs/source/user_guide/stability_policy.rst | 69 +++++++++++++++-- setup.cfg | 2 +- 7 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 docs/source/reference/accessor.rst create mode 100644 docs/source/user_guide/migration_1_0.rst diff --git a/docs/source/reference/accessor.rst b/docs/source/reference/accessor.rst new file mode 100644 index 000000000..3f7ae5499 --- /dev/null +++ b/docs/source/reference/accessor.rst @@ -0,0 +1,36 @@ +.. _reference.accessor: + +********************* +The ``.xrs`` accessor +********************* + +``import xrspatial`` registers an ``xrs`` accessor on ``xarray.DataArray`` +and ``xarray.Dataset``. Every method forwards to the top-level function of +the same name with the array as the first argument, so +``dem.xrs.slope()`` is ``xrspatial.slope(dem)``. + +The accessor is part of the 1.x LTS surface (see +:ref:`user_guide.stability_policy`). Methods that forward to +``xrspatial.experimental`` say so in their docstring and are not covered. + +.. code-block:: python + + import xrspatial + + dem = xrspatial.open_geotiff("dem.tif") + dem.xrs.slope() + dem.xrs.hillshade().xrs.to_geotiff("hillshade.tif") + +DataArray accessor +================== + +.. autoclass:: xrspatial.accessor.XrsSpatialDataArrayAccessor + :members: + :undoc-members: + +Dataset accessor +================ + +.. autoclass:: xrspatial.accessor.XrsSpatialDatasetAccessor + :members: + :undoc-members: diff --git a/docs/source/reference/geotiff_release_contract.md b/docs/source/reference/geotiff_release_contract.md index 0938c1c9b..a84c53c8c 100644 --- a/docs/source/reference/geotiff_release_contract.md +++ b/docs/source/reference/geotiff_release_contract.md @@ -26,9 +26,10 @@ deprecation window. You can rely on these in production. ### advanced -An `advanced` feature works and is tested, but its surface may change before a -1.0 release. Behaviour is documented and exercised by tests, but the contract is -narrower than `stable`. Edge cases on rare codecs, transport quirks on HTTP, and +An `advanced` feature works and is tested, and its function signature is +covered by the 1.x LTS promise, but the behavioural contract is narrower than +`stable` and edge-case behaviour may change in a minor release. Behaviour is +documented and exercised by tests. Edge cases on rare codecs, transport quirks on HTTP, and metadata interop with the wider GDAL ecosystem are not all pinned down. Use these in production with the expectation that you may need to follow a release-note migration. diff --git a/docs/source/reference/index.rst b/docs/source/reference/index.rst index d4603921b..53953374d 100644 --- a/docs/source/reference/index.rst +++ b/docs/source/reference/index.rst @@ -7,6 +7,7 @@ Reference .. toctree:: :maxdepth: 2 + accessor dask_laziness classification dasymetric diff --git a/docs/source/user_guide/index.rst b/docs/source/user_guide/index.rst index eb6dac94d..77939cfe5 100644 --- a/docs/source/user_guide/index.rst +++ b/docs/source/user_guide/index.rst @@ -21,3 +21,4 @@ User Guide attrs_contract geotiff_safe_io local-migration + migration_1_0 diff --git a/docs/source/user_guide/migration_1_0.rst b/docs/source/user_guide/migration_1_0.rst new file mode 100644 index 000000000..cb475a22c --- /dev/null +++ b/docs/source/user_guide/migration_1_0.rst @@ -0,0 +1,77 @@ +.. _migration_1_0: + +********************************** +Migrating from 0.x to 1.0 +********************************** + +xarray-spatial 1.0.0 removes the keyword and function aliases that 0.10.x had +deprecated. Each one warned with a ``DeprecationWarning`` that named its +replacement; from 1.0.0 the old spelling raises ``TypeError`` (for keyword +arguments) or ``AttributeError`` / ``ImportError`` (for functions). + +Everything else on the public surface is unchanged. If your code ran on +0.10.20 without warnings, it runs on 1.0.0. + +Removed aliases +=============== + +.. list-table:: + :header-rows: 1 + :widths: 40 40 20 + + * - Removed in 1.0.0 + - Use instead + - Deprecated since + * - ``xrspatial.basins`` / ``xrspatial.hydro.basins`` / ``basins_d8`` + - ``basin`` / ``basin_d8`` + - 0.10.x + * - ``crop(zones_ids=...)`` + - ``crop(zone_ids=...)`` + - 0.10.x + * - ``focal.apply(raster=...)`` and ``hotspots(raster=...)`` + - ``agg=`` + - 0.10.x + * - ``natural_breaks(agg, k, name, num_sample)`` positional ``num_sample`` + - ``natural_breaks(agg, k, num_sample=...)`` + - 0.10.x + * - ``rasterize(use_cuda=...)`` + - ``rasterize(gpu=...)`` + - 0.10.x + * - ``reproject(src_vertical_crs=..., tgt_vertical_crs=...)`` + - ``source_vertical_crs=``, ``target_vertical_crs=`` + - 0.10.x + * - ``open_geotiff(mask_nodata=...)`` + - ``open_geotiff(masked=...)``. Note the default is ``False``. + - 0.10.x + * - ``open_geotiff(name=...)`` + - ``open_geotiff(default_name=...)`` + - 0.10.x + * - ``open_geotiff(mask_and_scale=...)`` + - ``open_geotiff(unpack=...)`` + - 0.10.x + * - ``plot_geotiff(...)`` + - ``da.xrs.plot(...)`` + - 0.10.0 + * - ``owa(criterion_weights=...)`` + - ``owa(weights=...)`` + - 0.10.x + +Two private helpers also lost old spellings: the VRT writer's ``vrt_path=`` +and ``crs_wkt=`` (now ``path=`` and ``crs=``) and the GPU reader's +``gpu='auto'`` / ``gpu='strict'`` (now ``on_gpu_failure=``). Neither was +part of the public surface; ``open_geotiff`` takes ``gpu=True`` and +``on_gpu_failure='auto'|'strict'`` as before. + +Finding the old spellings +========================= + +Run your test suite on 0.10.20 with warnings turned into errors: + +.. code-block:: bash + + python -W error::DeprecationWarning -m pytest + +Every failure points at a line in the table above. + +See the :ref:`stability policy ` for how +deprecations work from 1.0 on. diff --git a/docs/source/user_guide/stability_policy.rst b/docs/source/user_guide/stability_policy.rst index b48f65431..867a5f694 100644 --- a/docs/source/user_guide/stability_policy.rst +++ b/docs/source/user_guide/stability_policy.rst @@ -4,17 +4,64 @@ Stability policy and LTS commitment =================================== This page states which parts of xarray-spatial are covered by long-term -support (LTS) in the 1.0.0 series, and what "stable" means here. +support (LTS) in the 1.x series, how deprecations work, and what "stable" +means here. + +Versioning +---------- + +xarray-spatial follows semantic versioning from 1.0.0 on. + +- Patch releases (1.0.1, 1.0.2, ...) fix bugs and do not change behaviour + for documented inputs. +- Minor releases (1.1.0, 1.2.0, ...) may add functions, add optional keyword + arguments, promote a function to a higher tier, raise a dependency floor, + and deprecate names. They do not remove or rename anything on the LTS + surface. +- Major releases (2.0.0) are the only place where deprecated names are + removed or where a documented contract changes incompatibly. What LTS covers --------------- -The high-level public spellings are the LTS surface: the names exported from -``xrspatial/__init__.py`` and the ``.xrs`` accessor on -``xarray.DataArray`` and ``xarray.Dataset``. Within the 1.0.x series these -names, their call signatures, and their documented return contracts do not -change in backward-incompatible ways. New optional keyword arguments may be -added; existing behavior for documented inputs is preserved. +The high-level public spellings are the LTS surface: + +- every name listed in ``xrspatial.__all__`` (the names you get from + ``import xrspatial``), +- the public names of the ``xrspatial.mcda`` subpackage, +- the ``.xrs`` accessor on ``xarray.DataArray`` and ``xarray.Dataset`` (see + :ref:`reference.accessor`). + +For the whole 1.x series these names, their call signatures, and their +documented return contracts do not change in backward-incompatible ways. +New optional keyword arguments may be added; existing behaviour for +documented inputs is preserved. + +Functions that live only in a submodule (for example +``xrspatial.experimental.min_observable_height``) and anything with a leading +underscore are not part of the LTS surface and may change in a minor release. + +Deprecation window +------------------ + +When a name or keyword argument on the LTS surface is replaced: + +1. The old spelling keeps working and emits a ``DeprecationWarning`` that + names the replacement and the release that will remove it. +2. The warning ships in at least one minor release before removal. +3. Removal happens in the next major release, never in a minor or patch. + +The 0.x aliases that 1.0.0 removed are listed on the +:ref:`migration_1_0` page. + +Dependencies +------------ + +The minimum supported Python and dependency versions are the ones pinned in +the ``min-deps`` job of the test workflow. Raising a floor is a minor-release +change and is called out in the changelog. The package declares an upper +bound on NumPy only; new NumPy minors are tested and the bound lifted in a +patch or minor release. What "stable" requires ---------------------- @@ -34,3 +81,11 @@ Tiers below stable caveats or make no cross-backend parity claim. GPU and some Dask paths usually stay at these tiers. The README feature matrix is the per-backend source of truth for each function's tier. + +Changing a tier +--------------- + +A tier moves in a pull request that edits the README matrix cell and states +the reason. Promotion can happen in any release. Demoting a cell from +``stable`` is an incompatible contract change and waits for a major release; +until then the behaviour stays and the caveat goes in the docs. diff --git a/setup.cfg b/setup.cfg index eaf34675b..a85743df3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [metadata] author = Xarray-Spatial Developers classifiers = - Development Status :: 4 - Beta + Development Status :: 5 - Production/Stable Intended Audience :: Developers Intended Audience :: Science/Research License :: OSI Approved :: MIT License From 31aa56da9babc1ef391aba4cd355da33e964177f Mon Sep 17 00:00:00 2001 From: Brendan Collins Date: Fri, 6 Nov 2026 10:17:42 -0500 Subject: [PATCH 2/3] Pin the deprecated-since column to the release that added each warning (#3760) --- docs/source/user_guide/migration_1_0.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/source/user_guide/migration_1_0.rst b/docs/source/user_guide/migration_1_0.rst index cb475a22c..490954995 100644 --- a/docs/source/user_guide/migration_1_0.rst +++ b/docs/source/user_guide/migration_1_0.rst @@ -24,37 +24,37 @@ Removed aliases - Deprecated since * - ``xrspatial.basins`` / ``xrspatial.hydro.basins`` / ``basins_d8`` - ``basin`` / ``basin_d8`` - - 0.10.x + - 0.10.2 * - ``crop(zones_ids=...)`` - ``crop(zone_ids=...)`` - - 0.10.x + - 0.10.1 * - ``focal.apply(raster=...)`` and ``hotspots(raster=...)`` - ``agg=`` - - 0.10.x + - 0.10.2 * - ``natural_breaks(agg, k, name, num_sample)`` positional ``num_sample`` - ``natural_breaks(agg, k, num_sample=...)`` - - 0.10.x + - 0.10.11 * - ``rasterize(use_cuda=...)`` - ``rasterize(gpu=...)`` - - 0.10.x + - 0.10.7 * - ``reproject(src_vertical_crs=..., tgt_vertical_crs=...)`` - ``source_vertical_crs=``, ``target_vertical_crs=`` - - 0.10.x + - 0.10.2 * - ``open_geotiff(mask_nodata=...)`` - ``open_geotiff(masked=...)``. Note the default is ``False``. - - 0.10.x + - 0.10.5 * - ``open_geotiff(name=...)`` - ``open_geotiff(default_name=...)`` - - 0.10.x + - 0.10.5 * - ``open_geotiff(mask_and_scale=...)`` - ``open_geotiff(unpack=...)`` - - 0.10.x + - 0.10.7 * - ``plot_geotiff(...)`` - ``da.xrs.plot(...)`` - 0.10.0 * - ``owa(criterion_weights=...)`` - ``owa(weights=...)`` - - 0.10.x + - 0.10.7 Two private helpers also lost old spellings: the VRT writer's ``vrt_path=`` and ``crs_wkt=`` (now ``path=`` and ``crs=``) and the GPU reader's From efd259c5190dfd051a84b392a32bb65fe06eb20e Mon Sep 17 00:00:00 2001 From: Brendan Collins Date: Fri, 6 Nov 2026 12:09:24 -0500 Subject: [PATCH 3/3] Add the accessor spellings of the basins and crop aliases to the migration table (#3760) --- docs/source/user_guide/migration_1_0.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/user_guide/migration_1_0.rst b/docs/source/user_guide/migration_1_0.rst index 490954995..791ad1746 100644 --- a/docs/source/user_guide/migration_1_0.rst +++ b/docs/source/user_guide/migration_1_0.rst @@ -22,11 +22,11 @@ Removed aliases * - Removed in 1.0.0 - Use instead - Deprecated since - * - ``xrspatial.basins`` / ``xrspatial.hydro.basins`` / ``basins_d8`` - - ``basin`` / ``basin_d8`` + * - ``xrspatial.basins`` / ``xrspatial.hydro.basins`` / ``basins_d8`` / ``.xrs.basins()`` + - ``basin`` / ``basin_d8`` / ``.xrs.basin()`` - 0.10.2 - * - ``crop(zones_ids=...)`` - - ``crop(zone_ids=...)`` + * - ``crop(zones_ids=...)`` and ``.xrs.crop(zones, zones_ids=...)`` + - ``crop(zone_ids=...)`` / ``.xrs.crop(zones, zone_ids=...)`` - 0.10.1 * - ``focal.apply(raster=...)`` and ``hotspots(raster=...)`` - ``agg=``