Skip to content

[rasterio] Add stubs for rasterio 1.5#15884

Open
thomas-maschler wants to merge 7 commits into
python:mainfrom
thomas-maschler:add-rasterio-stubs
Open

[rasterio] Add stubs for rasterio 1.5#15884
thomas-maschler wants to merge 7 commits into
python:mainfrom
thomas-maschler:add-rasterio-stubs

Conversation

@thomas-maschler
Copy link
Copy Markdown

Summary

Adds type stubs for rasterio tracking the current rasterio==1.5.* release.

Follow-up to #15870 — please refer to that issue for the discussion that shaped the PR's scope (in particular the decision to ship affine references through a stubs-only indirection instead of bundling types-affine).

Also addresses rasterio/rasterio#2322 (the upstream type-hinting tracker): rasterio's maintainers opted not to add inline annotations, so external stubs are the practical alternative — this PR provides them.

What's included

  • 43 stub files covering the rasterio 1.5 public API surface, plus the Cython _-prefixed modules transitively required by public re-exports (_base, _io, _warp, _env, _err, _features, _filepath, _path, _show_versions, _transform, _typing, _version, _vsiopener, _affine_types).
  • METADATA.toml with version = "1.5.*", requires-python = ">=3.12" (rasterio 1.5 itself requires 3.12+), dependencies = ["numpy>=2", "click>=8"], and a [tool.stubtest] section pinned to rasterio==1.5.* plus libgdal-dev / gdal apt/brew packages.
  • partial-stub = true — the entire public surface is covered, but a handful of internal Cython helpers are deliberately Incomplete.
  • @tests/stubtest_allowlist.txt for the remaining @disjoint_base markers / Cython-introspected parameter-name drift in a small set of private modules.
  • @tests/test_cases/check_{crs,dataset,open,transform_geom,windows}.py regression tests.

affine.Affine strategy

Per the discussion on #15870, rasterio's stubs reference affine.Affine through a single stubs-only indirection module (rasterio._affine_types) that aliases Affine to Any:

# rasterio/_affine_types.pyi
from typing import Any, TypeAlias

Affine: TypeAlias = Any

Affine v3 is currently in the 3.0rc3 pre-release and already ships complete inline type hints plus a py.typed marker (affine.py was moved to affine/__init__.py in rc3 specifically to enable that distribution). When v3 is final, the swap is one line in one file:

# rasterio/_affine_types.pyi
from affine import Affine as Affine

This avoids any need to ship types-affine in typeshed.

PEP 702 @deprecated markers

Cover every documented RasterioDeprecationWarning site, including the overload-based parameter deprecations:

  • warp.transform_geom(antimeridian_cutting=, antimeridian_offset=)
  • windows.from_bounds(height=, width=, precision=)
  • merge.merge(precision=)
  • features.geometry_window(north_up=, rotated=, pixel_precision=)
  • transform.TransformerBase.rowcol(precision=)
  • windows.WindowMethodsMixin.window(precision=)

…and whole-symbol cases: CRS.is_valid, Window.round_shape, DatasetReaderBase.statistics, DatasetBase.is_tiled, env.hascreds, env.ensure_env_credentialled, io.FilePath, path.parse_path, path.vsi_path.

Two deprecations cannot be expressed via overload because **rpc_options swallows the deprecated kwarg in the modern overload (transform.rowcol(precision=) and transform.TransformMethodsMixin.index(precision=)); these carry inline notes in the stub.

Local validation

Run against rasterio==1.5.0 in a fresh venv:

Check Result
check_typeshed_structure pass
mypy_test (3.10‑3.15) pass
regr_test rasterio pass
stubtest_third_party rasterio pass
pyright (basic settings) pass
ruff check + ruff format --check pass
flake8 --select=Y pass

Notes

  • WktVersion.WKT2_2019 = "WKT2_2018" — the stub mirrors this upstream quirk (likely a typo, but stubtest would flag any "correction").
  • plot.contrast_strech is misspelled upstream; the stub matches with an inline comment.
  • rasterio.rio.* (the CLI) is deliberately not stubbed.

thomas-maschler and others added 2 commits June 8, 2026 12:31
Covers the public rasterio 1.5.x API plus the private Cython modules
that are transitively required by public re-exports. `partial-stub =
true` (a handful of internal Cython helpers are `Incomplete`).

`affine.Affine` is referenced through a single stubs-only indirection
module (`rasterio._affine_types`) that aliases `Affine` to `Any` until
affine ships its own `py.typed` (planned for v3), per discussion in
issue python#15870. When affine v3 lands, replacing the body of
`_affine_types.pyi` with `from affine import Affine as Affine` will
restore precision package-wide in a single edit.

PEP 702 `@deprecated` markers cover every documented
`RasterioDeprecationWarning` site, including the overload-based
parameter deprecations (warp.transform_geom antimeridian_*,
windows.from_bounds height/width/precision, merge precision,
features.geometry_window north_up/rotated/pixel_precision,
transform.TransformerBase.rowcol precision, windows.WindowMethodsMixin
.window precision) and whole-symbol cases (CRS.is_valid, Window
.round_shape, DatasetReaderBase.statistics, DatasetBase.is_tiled,
env.hascreds, env.ensure_env_credentialled, io.FilePath,
rasterio.path.{parse_path,vsi_path}).

Closes python#15870 (in part; see issue for the affine-stubs decision).
@github-actions

This comment has been minimized.

thomas-maschler and others added 3 commits June 8, 2026 12:55
rasterio ships self-contained binary wheels for every platform/Python
combination typeshed CI targets (manylinux x86_64/aarch64, macOS
x86_64/arm64, Windows), so no system GDAL is needed for stubtest.

Removing libgdal-dev also unblocks the aggregate apt-install step:
libgdal-dev on Ubuntu noble hard-depends on default-libmysqlclient-dev,
whose libmysqlclient-dev provider is currently broken in the noble
archive.

Also strips justifying / explanatory comments throughout the stubs.
* check_open.py: rename `_opaque_mode` -> `check_opaque_mode` so the
  helper is no longer flagged as `reportUnusedFunction`.
* check_transform_geom.py: mark the two intentional deprecated-overload
  calls with `# pyright: ignore[reportDeprecated]` (they exist to
  exercise the `@deprecated` overload routing).
@github-actions

This comment has been minimized.

thomas-maschler and others added 2 commits June 8, 2026 13:15
`pyrightconfig.stricter.json` (which checks rasterio because the
package isn't on the exclude list) flagged
`_base._parse_path(path: str): ...` for an unknown return type
(`reportUnknownParameterType`) on every Darwin/Windows matrix combo.
The runtime forwards to `rasterio._path._parse_path`; mirror its
return annotation here.

Also apply ruff format to drop the blank lines between adjacent
class members (typeshed style; was getting re-applied by pre-commit-ci).
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

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.

1 participant