Skip to content

Commit ffac766

Browse files
add experimental features (#786)
1 parent 7db311c commit ffac766

File tree

8 files changed

+136
-1
lines changed

8 files changed

+136
-1
lines changed

CHANGES.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
# 7.5.0 (2025-02-26)
3+
4+
* add `rio_tiler.experimental` submodule
5+
* add `rio_tiler.experimental.vsifile.VSIReader` VSIFile based experimental reader
6+
27
# 7.4.0 (2025-01-28)
38

49
* update rasterio dependency to `>=1.4.0`

docs/mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ nav:
3131
- Mosaic: 'mosaic.md'
3232
- Colormaps: 'colormap.md'
3333
- Supported file formats: 'supported_format.md'
34+
- Experimental: experimental.md
3435
- Advanced Topics:
3536
- Base classes and custom readers: 'advanced/custom_readers.md'
3637
- Read Polygon-shaped regions: 'advanced/feature.md'

docs/src/experimental.md

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Experimental Features
2+
3+
In this section you will find documentation for new, experimental features in rio-tiler. These features are subject to change or removal, and we are looking for feedback and suggestions before making them a permanent part of Pydantic.
4+
5+
6+
## Feedback
7+
8+
We welcome feedback on experimental features! Please open an issue on the [rio-tiler GitHub repository](https://github.com/cogeotiff/rio-tiler/issues/new/choose) to share your thoughts, requests, or suggestions.
9+
10+
We also encourage you to read through existing feedback and add your thoughts to existing issues.
11+
12+
## Warnings on Import
13+
14+
When you import an experimental feature from the `experimental` module, you'll see a warning message that the feature is experimental. You can disable this warning with the following:
15+
16+
```python
17+
import warnings
18+
from rio_tiler.errors import RioTilerExperimentalWarning
19+
20+
warnings.filterwarnings('ignore', category=RioTilerExperimentalWarning)
21+
```
22+
23+
## VSIFile Reader
24+
25+
Required dependencies:
26+
- `vsifile>=0.2`
27+
28+
A rio-tiler Reader using VSIFile/Obstore as file system handler. Starting with GDAL>=3.0, **VSI plugin** was added in order to enable users to provide their own file system handler (class handling the file requests).
29+
30+
The reader is considered experimental because [`VSIFile`](https://github.com/vincentsarago/vsifile) is still under development. Users should also note that changes available in GDAL>=3.10 will drastically improve the performance of this reader (https://github.com/vincentsarago/vsifile/issues/13#issuecomment-2683310594)
31+
32+
```python
33+
from rio_tiler.experimental.vsifile import VSIReader
34+
35+
with VSIReader("https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/VK/2023/10/S2B_15TVK_20231008_0_L2A/TCI.tif") as src:
36+
print(src.info())
37+
38+
>>> bounds=(399960.0, 4890240.0, 509760.0, 5000040.0) crs='http://www.opengis.net/def/crs/EPSG/0/32615' band_metadata=[('b1', {}), ('b2', {}), ('b3', {})] band_descriptions=[('b1', ''), ('b2', ''), ('b3', '')] dtype='uint8' nodata_type='Nodata' colorinterp=['red', 'green', 'blue'] scales=[1.0, 1.0, 1.0] offsets=[0.0, 0.0, 0.0] colormap=None driver='GTiff' count=3 width=10980 height=10980 overviews=[2, 4, 8, 16] nodata_value=0.0
39+
```
40+
41+
#### Links
42+
43+
- https://github.com/OSGeo/gdal/pull/1289
44+
- https://github.com/rasterio/rasterio/pull/2141

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ dependencies = [
3838
test = [
3939
"pytest",
4040
"pytest-cov",
41-
4241
# XarrayReader
4342
"xarray",
4443
"rioxarray",
@@ -47,6 +46,8 @@ test = [
4746
"boto3",
4847
# Some tests will fail with 5.0
4948
"morecantile>=6.0,<7.0",
49+
# Experimental
50+
"vsifile>=0.2",
5051
]
5152

5253
benchmark = [

rio_tiler/errors.py

+4
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,7 @@ class MissingCRS(RioTilerError):
9191

9292
class InvalidGeographicBounds(RioTilerError):
9393
"""Invalid Geographic bounds."""
94+
95+
96+
class RioTilerExperimentalWarning(UserWarning):
97+
"""A rio-tiler specific experimental functionality warning."""

rio_tiler/experimental/__init__.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""The "experimental" module of rio-tiler contains potential new features that are subject to change."""
2+
3+
import warnings
4+
5+
from rio_tiler.errors import RioTilerExperimentalWarning
6+
7+
warnings.warn(
8+
"This module is experimental, its contents are subject to change and deprecation.",
9+
category=RioTilerExperimentalWarning,
10+
)

rio_tiler/experimental/vsifile.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""rio_tiler.io.Reader with VSIFILE/Obstore Opener."""
2+
3+
from typing import Union
4+
5+
import attr
6+
import rasterio
7+
from rasterio.io import DatasetReader, DatasetWriter, MemoryFile
8+
from rasterio.vrt import WarpedVRT
9+
10+
from rio_tiler.io import Reader
11+
12+
try:
13+
import vsifile
14+
from vsifile.rasterio import opener
15+
except ImportError: # pragma: nocover
16+
vsifile = None # type: ignore
17+
opener = None # type: ignore
18+
19+
20+
@attr.s
21+
class VSIReader(Reader):
22+
"""Rasterio Reader with VSIFILE opener."""
23+
24+
dataset: Union[DatasetReader, DatasetWriter, MemoryFile, WarpedVRT] = attr.ib(
25+
default=None, init=False
26+
)
27+
28+
def __attrs_post_init__(self):
29+
"""Use vsifile.rasterio.opener as Python file opener."""
30+
assert vsifile is not None, "VSIFILE must be installed to use VSIReader"
31+
32+
self.dataset = self._ctx_stack.enter_context(
33+
rasterio.open(self.input, opener=opener)
34+
)
35+
36+
super().__attrs_post_init__()

tests/test_io_vsifile.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""test VSIReader."""
2+
3+
import os
4+
5+
import numpy
6+
import pytest
7+
8+
from rio_tiler.errors import RioTilerExperimentalWarning
9+
from rio_tiler.io import Reader
10+
11+
PREFIX = os.path.join(os.path.dirname(__file__), "fixtures")
12+
COGEO = os.path.join(PREFIX, "cog.tif")
13+
14+
15+
def test_vsireader():
16+
"""Test Reader using VSIFile handler."""
17+
pytest.importorskip("vsifile")
18+
19+
with pytest.warns((RioTilerExperimentalWarning)):
20+
from rio_tiler.experimental.vsifile import VSIReader
21+
22+
# VSIReader doesn't take dataset as input
23+
with pytest.raises(TypeError):
24+
with VSIReader(COGEO, dataset="cog"):
25+
pass
26+
27+
with VSIReader(COGEO) as vsi, Reader(COGEO) as src:
28+
assert vsi.bounds == src.bounds
29+
assert vsi.crs == src.crs
30+
assert vsi.info().model_dump() == src.info().model_dump()
31+
32+
img_vsi = vsi.preview()
33+
img_src = src.preview()
34+
assert numpy.array_equal(img_vsi.array, img_src.array)

0 commit comments

Comments
 (0)