Commit b8c5fe7
committed
write_vrt: accept crs= for parity with to_geotiff/write_geotiff_gpu (#1715)
The api-consistency sweep on 2026-05-12 found ``write_vrt`` was the only
writer in ``xrspatial.geotiff`` using ``crs_wkt`` instead of ``crs``:
to_geotiff(data, path, *, crs: int | str | None = None, ...)
write_geotiff_gpu(data, path, *, crs: int | str | None = None, ...)
write_vrt(vrt_path, source_files, *, crs_wkt: str | None = None, ...)
This broke the "forward the same kwargs to whichever writer matches the
output extension" pattern. Generic write-wrapper code had to special-case
VRT, convert EPSG int -> WKT for that path, and remember that one writer
in the trio used a different name. Reader-side ``attrs['crs']`` is the
canonical EPSG-int surface, so the asymmetry is also visible in
round-trip code.
This change adds ``crs`` as the canonical kwarg with the same
``int | str | None`` shape as the sibling writers. ``crs_wkt`` is kept
as a deprecated alias for backward compatibility:
* ``crs=`` accepts int (EPSG), str (WKT or PROJ), or None.
* ``crs_wkt=`` still works but emits ``DeprecationWarning``.
* Passing both raises ``TypeError`` rather than silently picking one.
* Omitting both (the most common call shape) emits NO warning.
The wrapper normalises any non-None input through the new
``_resolve_crs_to_wkt`` helper before forwarding to the internal
``_vrt.write_vrt`` (which only speaks WKT). EPSG int and PROJ-string
inputs are routed through pyproj's ``CRS.from_user_input(...).to_wkt()``;
already-WKT strings (recognised by the PROJCS/GEOGCS/PROJCRS/GEOGCRS/
COMPD_CS/COMPOUNDCRS prefix) pass through verbatim so the existing
WKT-passthrough behaviour for the XML-escape tests is preserved.
The deprecation shim follows the same sentinel-default pattern the
deprecated ``gpu=`` alias uses on ``read_geotiff_gpu``: a private
``_CRS_WKT_DEPRECATED_SENTINEL`` distinguishes "user passed nothing"
(silent) from "user passed ``crs_wkt=None`` explicitly" (warn).
test_write_vrt_crs_1715.py adds 12 tests pinning the new contract:
* signature pins (``crs`` present, default None, annotation
``int | str | None``);
* runtime: ``crs=<EPSG int>``, ``crs=<WKT string>``, ``crs=None``,
no-crs-kwarg-no-warning, all round-trip back to ``attrs['crs']``;
* deprecation shim: ``crs_wkt=<wkt>`` warns + still works,
``crs_wkt=None`` (explicit) warns, both-kwargs raises ``TypeError``;
* cross-writer parity: ``crs`` annotation matches on all three writers;
* negative tests: invalid type / unparseable string raise on the public
wrapper.
Existing tests that were calling ``write_vrt(..., crs_wkt=...)`` through
the public wrapper are migrated to ``crs=`` so the suite no longer emits
spurious DeprecationWarnings:
* ``test_polish_1488.py``: ``crs=None`` replaces ``crs_wkt=None``.
* ``test_kwarg_behaviour_2026_05_12.py::TestWriteVrtCrsWktBehaviour``:
three sub-tests migrated from ``crs_wkt=`` to ``crs=``.
* ``test_signature_parity_1631.py``: signature test updated to assert
both kwargs and uses ``crs=None`` in the runtime call.
``test_vrt_xml_escape_1607.py`` keeps using ``crs_wkt=`` because it
imports from the internal ``xrspatial.geotiff._vrt`` (not the public
wrapper) and exercises raw XML-escape semantics; the rename does not
apply there.
Closes #1715.1 parent 0699aae commit b8c5fe7
5 files changed
Lines changed: 402 additions & 21 deletions
File tree
- xrspatial/geotiff
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
77 | 83 | | |
78 | 84 | | |
79 | 85 | | |
| |||
153 | 159 | | |
154 | 160 | | |
155 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
156 | 247 | | |
157 | 248 | | |
158 | 249 | | |
| |||
3450 | 3541 | | |
3451 | 3542 | | |
3452 | 3543 | | |
3453 | | - | |
| 3544 | + | |
| 3545 | + | |
3454 | 3546 | | |
3455 | 3547 | | |
3456 | 3548 | | |
| |||
3462 | 3554 | | |
3463 | 3555 | | |
3464 | 3556 | | |
3465 | | - | |
3466 | | - | |
3467 | | - | |
| 3557 | + | |
| 3558 | + | |
| 3559 | + | |
| 3560 | + | |
| 3561 | + | |
| 3562 | + | |
| 3563 | + | |
| 3564 | + | |
| 3565 | + | |
| 3566 | + | |
| 3567 | + | |
3468 | 3568 | | |
3469 | 3569 | | |
3470 | 3570 | | |
| |||
3478 | 3578 | | |
3479 | 3579 | | |
3480 | 3580 | | |
3481 | | - | |
3482 | | - | |
| 3581 | + | |
| 3582 | + | |
| 3583 | + | |
| 3584 | + | |
| 3585 | + | |
| 3586 | + | |
| 3587 | + | |
| 3588 | + | |
| 3589 | + | |
| 3590 | + | |
| 3591 | + | |
| 3592 | + | |
| 3593 | + | |
| 3594 | + | |
| 3595 | + | |
| 3596 | + | |
| 3597 | + | |
| 3598 | + | |
| 3599 | + | |
| 3600 | + | |
| 3601 | + | |
| 3602 | + | |
| 3603 | + | |
| 3604 | + | |
| 3605 | + | |
3483 | 3606 | | |
3484 | 3607 | | |
3485 | 3608 | | |
3486 | 3609 | | |
3487 | | - | |
| 3610 | + | |
3488 | 3611 | | |
3489 | 3612 | | |
3490 | 3613 | | |
| |||
Lines changed: 12 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
204 | 204 | | |
205 | 205 | | |
206 | 206 | | |
207 | | - | |
208 | | - | |
209 | | - | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
210 | 217 | | |
211 | 218 | | |
212 | 219 | | |
| |||
221 | 228 | | |
222 | 229 | | |
223 | 230 | | |
224 | | - | |
| 231 | + | |
225 | 232 | | |
226 | 233 | | |
227 | 234 | | |
| |||
254 | 261 | | |
255 | 262 | | |
256 | 263 | | |
257 | | - | |
| 264 | + | |
258 | 265 | | |
259 | 266 | | |
260 | 267 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
92 | | - | |
93 | | - | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
94 | 97 | | |
95 | 98 | | |
96 | 99 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | | - | |
| 54 | + | |
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
58 | 62 | | |
59 | 63 | | |
60 | 64 | | |
61 | 65 | | |
62 | | - | |
| 66 | + | |
| 67 | + | |
63 | 68 | | |
64 | | - | |
65 | 69 | | |
66 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
67 | 80 | | |
68 | | - | |
| 81 | + | |
69 | 82 | | |
70 | 83 | | |
71 | 84 | | |
| |||
88 | 101 | | |
89 | 102 | | |
90 | 103 | | |
91 | | - | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
92 | 110 | | |
93 | 111 | | |
94 | 112 | | |
| |||
101 | 119 | | |
102 | 120 | | |
103 | 121 | | |
104 | | - | |
| 122 | + | |
105 | 123 | | |
106 | 124 | | |
107 | 125 | | |
| |||
0 commit comments