Skip to content

Commit

Permalink
make terracotta python 3.12 compatible (#346)
Browse files Browse the repository at this point in the history
* make terracotta python 3.12 compatible

fix deprecation/removal of pkg_resources and rasterio is_tiled

* implement is_tiled as a separate function

* drop support for python 3.8
  • Loading branch information
jkittner authored Oct 24, 2024
1 parent 4ac20dd commit 265dd5d
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 20 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:

matrix:
os: [ubuntu-latest]
python-version: ["3.8", "3.11"]
python-version: ["3.9", "3.12"]

defaults:
run:
Expand Down Expand Up @@ -107,7 +107,7 @@ jobs:

matrix:
os: [macos-latest, windows-latest]
python-version: ["3.8", "3.11"]
python-version: ["3.9", "3.12"]

defaults:
run:
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ to create a new environment containing all dependencies and Terracotta:
$ conda env create -f environment.yml
If you already have Python 3.8 (or above) installed, you can just run
If you already have Python 3.9 (or above) installed, you can just run

.. code-block:: bash
Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Try out a live demo `here <https://terracotta-demo-frontend.orangebeach-11aa4896
Installation
------------

If you are using Linux and already have Python 3.8+ installed, all you need to
If you are using Linux and already have Python 3.9+ installed, all you need to
do to check out Terracotta is

.. code-block:: bash
Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ channels:
- conda-forge
- nodefaults
dependencies:
- python>=3.8
- python>=3.9
- numpy
- rasterio>=1.3.0
- shapely
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
"Development Status :: 4 - Beta",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Framework :: Flask",
"Operating System :: Microsoft :: Windows :: Windows 10",
"Operating System :: MacOS :: MacOS X",
Expand All @@ -53,7 +53,7 @@
],
# module
packages=find_packages(exclude=["docs", "tests"]),
python_requires=">=3.8",
python_requires=">=3.9",
use_scm_version={"write_to": "terracotta/_version.py"},
# dependencies
setup_requires=[
Expand Down
10 changes: 4 additions & 6 deletions terracotta/cmaps/get_cmaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@
Define an interface to retrieve stored color maps.
"""

import importlib.resources
from typing import Dict
import os
from pkg_resources import resource_filename, Requirement, DistributionNotFound

import numpy as np


SUFFIX = "_rgba.npy"
EXTRA_CMAP_FOLDER = os.environ.get("TC_EXTRA_CMAP_FOLDER", "")

try:
PACKAGE_DIR = resource_filename(
Requirement.parse("terracotta"), "terracotta/cmaps/data"
)
except DistributionNotFound:
PACKAGE_DIR = str(importlib.resources.files("terracotta") / "cmaps/data")
except ModuleNotFoundError:
# terracotta was not installed, fall back to file system
PACKAGE_DIR = os.path.join(os.path.dirname(__file__), "data")

Expand Down
20 changes: 18 additions & 2 deletions terracotta/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import rasterio
from rasterio.env import GDALVersion
from rasterio._base import DatasetBase

ValidationInfo = Tuple[List[str], List[str], Dict[str, Any]]

Expand All @@ -22,6 +23,21 @@ def validate(src_path: str, strict: bool = True) -> bool:
return not errors


def is_tiled(src: DatasetBase) -> bool:
"""
Check if a rasterio dataset is tiled.
Implementation copied from
https://github.com/rasterio/rasterio/blob/74ccaf126d08fc6eca3eacd7cb20ac8bb155ee3b/rasterio/_base.pyx#L1006-L1017
Since this was deprecated in rasterio
:param src: rasterio dataset
"""
# It's rare but possible that a dataset's bands have different block structure.
# Therefore we check them all against the width of the dataset.
return src.block_shapes and all(src.width != w for _, w in src.block_shapes)


def check_raster_file(src_path: str) -> ValidationInfo: # pragma: no cover
"""
Implementation from
Expand Down Expand Up @@ -51,7 +67,7 @@ def check_raster_file(src_path: str) -> ValidationInfo: # pragma: no cover

overviews = src.overviews(1)
if src.width > 512 and src.height > 512:
if not src.is_tiled:
if not is_tiled(src):
errors.append(
"The file is greater than 512xH or 512xW, but is not tiled"
)
Expand Down Expand Up @@ -166,7 +182,7 @@ def check_raster_file(src_path: str) -> ValidationInfo: # pragma: no cover
for ix, dec in enumerate(overviews):
with rasterio.open(src_path, OVERVIEW_LEVEL=ix) as ovr_dst:
if ovr_dst.width > 512 and ovr_dst.height > 512:
if not ovr_dst.is_tiled:
if not is_tiled(ovr_dst):
errors.append("Overview of index {} is not tiled".format(ix))

return errors, warnings, details
13 changes: 8 additions & 5 deletions tests/cmaps/test_get_cmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,22 @@ def test_get_cmap():


def test_get_cmap_filesystem(monkeypatch):
import pkg_resources
import importlib
import importlib.resources

import terracotta.cmaps.get_cmaps

def throw_error(*args, **kwargs):
raise pkg_resources.DistributionNotFound("monkeypatched")
raise ModuleNotFoundError("monkeypatched")

with monkeypatch.context() as m:
m.setattr(pkg_resources.Requirement, "parse", throw_error)
m.setattr(importlib.resources, "files", throw_error)

with pytest.raises(pkg_resources.DistributionNotFound):
pkg_resources.Requirement.parse("terracotta")
with pytest.raises(ModuleNotFoundError) as exc_info:
importlib.resources.files("terracotta")

(msg,) = exc_info.value.args
assert msg == "monkeypatched"

importlib.reload(terracotta.cmaps.get_cmaps)

Expand Down

0 comments on commit 265dd5d

Please sign in to comment.