Skip to content

Commit

Permalink
add python 3.12 and switch to ruff-formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentsarago committed Apr 5, 2024
1 parent 2a75ea9 commit 4c2fd69
Show file tree
Hide file tree
Showing 21 changed files with 78 additions and 129 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
- '*'
pull_request:
env:
LATEST_PY_VERSION: '3.10'
LATEST_PY_VERSION: '3.11'

jobs:
tests:
Expand All @@ -21,6 +21,7 @@ jobs:
- '3.9'
- '3.10'
- '3.11'
- '3.12'

steps:
- uses: actions/checkout@v3
Expand Down
15 changes: 5 additions & 10 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,21 @@ repos:
hooks:
- id: validate-pyproject

- repo: https://github.com/psf/black
rev: 22.12.0
hooks:
- id: black
language_version: python

- repo: https://github.com/PyCQA/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
language_version: python

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.238
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.5
hooks:
- id: ruff
args: ["--fix"]
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.991
rev: v1.9.0
hooks:
- id: mypy
language_version: python
Expand Down
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@

# 6.4.5 (2024-04-05)

* add python 3.12 official support
* change code formatter to `ruff-format`

# 6.4.4 (2024-04-02)

* better handler `NaN` nodata values for masking (author @cerolinx, https://github.com/cogeotiff/rio-tiler/pull/691)
Expand Down
1 change: 1 addition & 0 deletions docs/scripts/colormap_thumb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
This file is derived from the matplotlib documentation.
https://matplotlib.org/tutorials/colors/colormaps.html
"""

from pathlib import Path

import matplotlib.pyplot as plt
Expand Down
8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering :: GIS",
]
dynamic = ["version"]
Expand Down Expand Up @@ -129,6 +130,9 @@ default_section = "THIRDPARTY"
no_strict_optional = true

[tool.ruff]
line-length = 90

[tool.ruff.lint]
select = [
"D1", # pydocstyle errors
"E", # pycodestyle errors
Expand All @@ -141,4 +145,8 @@ ignore = [
"E501", # line too long, handled by black
"B008", # do not perform function calls in argument defaults
"B905", # ignore zip() without an explicit strict= parameter, only support with python >3.10
"B028",
]

[tool.ruff.lint.mccabe]
max-complexity = 14
13 changes: 7 additions & 6 deletions rio_tiler/colormap.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
EMPTY_COLORMAP: GDALColorMapType = {i: (0, 0, 0, 0) for i in range(256)}

DEFAULT_CMAPS_FILES = {
f.stem: str(f) for f in (resources_files(__package__) / "cmap_data").glob("*.npy") # type: ignore
f.stem: str(f)
for f in (resources_files(__package__) / "cmap_data").glob("*.npy") # type: ignore
}

USER_CMAPS_DIR = os.environ.get("COLORMAP_DIRECTORY", None)
Expand Down Expand Up @@ -123,9 +124,7 @@ def apply_cmap(data: numpy.ndarray, colormap: ColorMapType) -> DataMaskType:
return data[:-1], data[-1]


def apply_discrete_cmap(
data: numpy.ndarray, colormap: GDALColorMapType
) -> DataMaskType:
def apply_discrete_cmap(data: numpy.ndarray, colormap: GDALColorMapType) -> DataMaskType:
"""Apply discrete colormap.
Args:
Expand Down Expand Up @@ -189,7 +188,7 @@ def apply_intervals_cmap(
"""
res = numpy.zeros((data.shape[1], data.shape[2], 4), dtype=numpy.uint8)

for (k, v) in colormap:
for k, v in colormap:
res[(data[0] >= k[0]) & (data[0] < k[1])] = numpy.array(v)

data = numpy.transpose(res, [2, 0, 1])
Expand Down Expand Up @@ -251,7 +250,9 @@ def parse_color(rgba: Union[Sequence[int], str]) -> Tuple[int, int, int, int]:

match = re.match(hex_pattern, rgba)
rgba = [
int(n * factor, 16) for n in match.groupdict().values() if n is not None # type: ignore
int(n * factor, 16)
for n in match.groupdict().values()
if n is not None # type: ignore
]

if len(rgba) > 4 or len(rgba) < 3:
Expand Down
4 changes: 1 addition & 3 deletions rio_tiler/io/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,9 +901,7 @@ def parse_expression(self, expression: str) -> Tuple:

return bands

def info(
self, bands: Union[Sequence[str], str] = None, *args, **kwargs: Any
) -> Info:
def info(self, bands: Union[Sequence[str], str] = None, *args, **kwargs: Any) -> Info:
"""Return metadata from multiple bands.
Args:
Expand Down
4 changes: 1 addition & 3 deletions rio_tiler/io/rasterio.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,7 @@ def _get_descr(ix):
meta.update({"colormap": self.colormap})

if nodata_type == "Nodata":
meta.update(
{"nodata_value": self.options.get("nodata", self.dataset.nodata)}
)
meta.update({"nodata_value": self.options.get("nodata", self.dataset.nodata)})

return Info(**meta)

Expand Down
4 changes: 1 addition & 3 deletions rio_tiler/io/stac.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,7 @@ def __attrs_post_init__(self):
)
)
if not self.assets:
raise MissingAssets(
"No valid asset found. Asset's media types not supported"
)
raise MissingAssets("No valid asset found. Asset's media types not supported")

@minzoom.default
def _minzoom(self):
Expand Down
5 changes: 2 additions & 3 deletions rio_tiler/io/xarray.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""rio_tiler.io.xarray: Xarray Reader."""

from __future__ import annotations

import warnings
Expand Down Expand Up @@ -231,9 +232,7 @@ def tile(
reproject_method = resampling_method

if not self.tile_exists(tile_x, tile_y, tile_z):
raise TileOutsideBounds(
f"Tile {tile_z}/{tile_x}/{tile_y} is outside bounds"
)
raise TileOutsideBounds(f"Tile {tile_z}/{tile_x}/{tile_y} is outside bounds")

ds = self.input
if nodata is not None:
Expand Down
20 changes: 7 additions & 13 deletions rio_tiler/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def create_from_list(cls, data: Sequence["PointData"]):
raise InvalidPointDataError("Empty PointData list.")

# validate coordinates
if all([pt.coordinates or pt.crs or None for pt in data]):
if all(pt.coordinates or pt.crs or None for pt in data):
lon, lat, crs = zip(*[(*(pt.coordinates or []), pt.crs) for pt in data])
if len(set(lon)) > 1 or len(set(lat)) > 1 or len(set(crs)) > 1:
raise InvalidPointDataError(
Expand All @@ -245,9 +245,7 @@ def create_from_list(cls, data: Sequence["PointData"]):
)

band_names = list(
itertools.chain.from_iterable(
[pt.band_names for pt in data if pt.band_names]
)
itertools.chain.from_iterable([pt.band_names for pt in data if pt.band_names])
)

metadata = dict(
Expand Down Expand Up @@ -439,9 +437,7 @@ def create_from_list(cls, data: Sequence["ImageData"]) -> "ImageData":
# Get cutline mask at highest resolution.
max_h, max_w = max(h), max(w)
cutline_mask = next(
img.cutline_mask
for img in data
if img.height == max_h and img.width == max_w
img.cutline_mask for img in data if img.height == max_h and img.width == max_w
)

if len(set(h)) > 1 or len(set(w)) > 1:
Expand All @@ -462,9 +458,7 @@ def create_from_list(cls, data: Sequence["ImageData"]) -> "ImageData":

assets = list(
dict.fromkeys(
itertools.chain.from_iterable(
[img.assets for img in data if img.assets]
)
itertools.chain.from_iterable([img.assets for img in data if img.assets])
)
)

Expand Down Expand Up @@ -627,9 +621,9 @@ def resize(
) -> "ImageData":
"""Resize data and mask."""
data = resize_array(self.array.data, height, width, resampling_method)
mask = resize_array(
self.array.mask * 1, height, width, resampling_method
).astype("bool")
mask = resize_array(self.array.mask * 1, height, width, resampling_method).astype(
"bool"
)

return ImageData(
numpy.ma.MaskedArray(data, mask=mask),
Expand Down
31 changes: 8 additions & 23 deletions rio_tiler/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import contextlib
import math
import warnings
from enum import IntEnum
from typing import Callable, Dict, Optional, Tuple, TypedDict, Union

import numpy
from affine import Affine
from rasterio import windows
from rasterio.crs import CRS
from rasterio.enums import ColorInterp, MaskFlags, Resampling
from rasterio.enums import ColorInterp, Resampling
from rasterio.io import DatasetReader, DatasetWriter
from rasterio.transform import array_bounds
from rasterio.vrt import WarpedVRT
Expand Down Expand Up @@ -97,9 +96,7 @@ def read(
resampling_method: RIOResampling = "nearest",
reproject_method: WarpResampling = "nearest",
unscale: bool = False,
post_process: Optional[
Callable[[numpy.ma.MaskedArray], numpy.ma.MaskedArray]
] = None,
post_process: Optional[Callable[[numpy.ma.MaskedArray], numpy.ma.MaskedArray]] = None,
) -> ImageData:
"""Low level read function.
Expand Down Expand Up @@ -196,9 +193,7 @@ def read(
values = dataset.read(
indexes=indexes,
window=window,
out_shape=(len(indexes), height, width)
if height and width
else None,
out_shape=(len(indexes), height, width) if height and width else None,
resampling=io_resampling,
boundless=boundless,
)
Expand Down Expand Up @@ -246,9 +241,7 @@ def read(
stats = []
for ix in indexes:
tags = dataset.tags(ix)
if all(
stat in tags for stat in ["STATISTICS_MINIMUM", "STATISTICS_MAXIMUM"]
):
if all(stat in tags for stat in ["STATISTICS_MINIMUM", "STATISTICS_MAXIMUM"]):
stat_min = float(tags.get("STATISTICS_MINIMUM"))
stat_max = float(tags.get("STATISTICS_MAXIMUM"))
stats.append((stat_min, stat_max))
Expand Down Expand Up @@ -302,9 +295,7 @@ def part(
resampling_method: RIOResampling = "nearest",
reproject_method: WarpResampling = "nearest",
unscale: bool = False,
post_process: Optional[
Callable[[numpy.ma.MaskedArray], numpy.ma.MaskedArray]
] = None,
post_process: Optional[Callable[[numpy.ma.MaskedArray], numpy.ma.MaskedArray]] = None,
) -> ImageData:
"""Read part of a dataset.
Expand Down Expand Up @@ -352,12 +343,8 @@ def part(
src_bounds = transform_bounds(
src_dst.crs, dst_crs, *src_dst.bounds, densify_pts=21
)
x_overlap = max(
0, min(src_bounds[2], bounds[2]) - max(src_bounds[0], bounds[0])
)
y_overlap = max(
0, min(src_bounds[3], bounds[3]) - max(src_bounds[1], bounds[1])
)
x_overlap = max(0, min(src_bounds[2], bounds[2]) - max(src_bounds[0], bounds[0]))
y_overlap = max(0, min(src_bounds[3], bounds[3]) - max(src_bounds[1], bounds[1]))
cover_ratio = (x_overlap * y_overlap) / (
(bounds[2] - bounds[0]) * (bounds[3] - bounds[1])
)
Expand Down Expand Up @@ -500,9 +487,7 @@ def point(
resampling_method: RIOResampling = "nearest",
reproject_method: WarpResampling = "nearest",
unscale: bool = False,
post_process: Optional[
Callable[[numpy.ma.MaskedArray], numpy.ma.MaskedArray]
] = None,
post_process: Optional[Callable[[numpy.ma.MaskedArray], numpy.ma.MaskedArray]] = None,
) -> PointData:
"""Read a pixel value for a point.
Expand Down
6 changes: 2 additions & 4 deletions rio_tiler/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def filter_tasks(
if allowed_exceptions is None:
allowed_exceptions = ()

for (future, asset) in tasks:
for future, asset in tasks:
try:
if isinstance(future, futures.Future):
yield future.result(), asset
Expand All @@ -52,9 +52,7 @@ def create_tasks(
]
else:
logger.debug(f"Running tasks outside ThreadsPool (max_workers={threads})")
return [
(partial(reader, asset, *args, **kwargs), asset) for asset in asset_list
]
return [(partial(reader, asset, *args, **kwargs), asset) for asset in asset_list]


def multi_arrays(
Expand Down
17 changes: 9 additions & 8 deletions rio_tiler/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,12 @@ def get_array_statistics(
percentiles_names = [f"percentile_{int(p)}" for p in percentiles]

if coverage is not None:
assert coverage.shape == (
data.shape[1],
data.shape[2],
assert (
coverage.shape
== (
data.shape[1],
data.shape[2],
)
), f"Invalid shape ({coverage.shape}) for Coverage, expected {(data.shape[1], data.shape[2])}"

else:
Expand Down Expand Up @@ -395,7 +398,7 @@ def get_vrt_transform(
def has_alpha_band(src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT]) -> bool:
"""Check for alpha band or mask in source."""
if (
any([MaskFlags.alpha in flags for flags in src_dst.mask_flag_enums])
any(MaskFlags.alpha in flags for flags in src_dst.mask_flag_enums)
or ColorInterp.alpha in src_dst.colorinterp
):
return True
Expand All @@ -405,10 +408,8 @@ def has_alpha_band(src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT]) -> b
def has_mask_band(src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT]) -> bool:
"""Check for mask band in source."""
if any(
[
(MaskFlags.per_dataset in flags and MaskFlags.alpha not in flags)
for flags in src_dst.mask_flag_enums
]
(MaskFlags.per_dataset in flags and MaskFlags.alpha not in flags)
for flags in src_dst.mask_flag_enums
):
return True
return False
Expand Down
Loading

0 comments on commit 4c2fd69

Please sign in to comment.