[Git][debian-gis-team/morecantile][upstream] New upstream version 7.1.0
Antonio Valentino (@antonio.valentino)
gitlab at salsa.debian.org
Wed Sep 16 20:37:11 BST 2026
Antonio Valentino pushed to branch upstream at Debian GIS Project / morecantile
Commits:
d5e28bfd by Antonio Valentino at 2026-09-16T19:31:53+00:00
New upstream version 7.1.0
- - - - -
14 changed files:
- + .github/dependabot.yml
- + .github/workflows/benchmark.yml
- .github/workflows/ci.yml
- .github/workflows/deploy_mkdocs.yml
- + .github/workflows/release.yml
- .pre-commit-config.yaml
- CHANGES.md
- morecantile/__init__.py
- morecantile/models.py
- morecantile/scripts/cli.py
- pyproject.toml
- tests/test_models.py
- tests/test_morecantile.py
- uv.lock
Changes:
=====================================
.github/dependabot.yml
=====================================
@@ -0,0 +1,21 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ groups:
+ all:
+ patterns:
+ - "*"
+ - package-ecosystem: uv
+ cooldown:
+ default-days: 7
+ directory: "/"
+ schedule:
+ interval: weekly
+ groups:
+ all:
+ patterns:
+ - "*"
\ No newline at end of file
=====================================
.github/workflows/benchmark.yml
=====================================
@@ -0,0 +1,54 @@
+name: Benchmark
+
+on:
+ push:
+ branches:
+ - main
+ tags:
+ - '*'
+ pull_request:
+ workflow_dispatch:
+
+permissions:
+ contents: write
+ pull-requests: write
+
+env:
+ LATEST_PY_VERSION: '3.14'
+
+jobs:
+ benchmark:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout at 3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+
+ - name: Install uv
+ uses: astral-sh/setup-uv at bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
+ with:
+ version: "0.9.*"
+ enable-cache: false
+ python-version: ${{ env.LATEST_PY_VERSION }}
+
+ - name: Install dependencies
+ run: |
+ uv sync --group benchmark --frozen
+
+ - name: Run Benchmark
+ run: |
+ uv run pytest tests/benchmarks.py --benchmark-only --benchmark-columns 'min, max, mean, median' --benchmark-sort 'min' --benchmark-json output.json
+
+ - name: Store and Compare benchmark result
+ uses: benchmark-action/github-action-benchmark at 52576c92bccf6ac60c8223ec7eb2565637cae9ba # v1
+ with:
+ name: morecantile Benchmarks
+ tool: 'pytest'
+ output-file-path: output.json
+ alert-threshold: '150%'
+ comment-on-alert: true
+ fail-on-alert: false
+ # GitHub API token to make a commit comment
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ gh-pages-branch: 'gh-benchmarks'
+ # Make a commit on `gh-pages` only if main
+ auto-push: ${{ github.ref == 'refs/heads/main' }}
+ benchmark-data-dir-path: dev/benchmarks
=====================================
.github/workflows/ci.yml
=====================================
@@ -18,10 +18,10 @@ jobs:
python-version: ['3.11', '3.12', '3.13', '3.14']
steps:
- - uses: actions/checkout at v5
+ - uses: actions/checkout at 3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install uv
- uses: astral-sh/setup-uv at v7
+ uses: astral-sh/setup-uv at bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.9.*"
enable-cache: true
@@ -41,84 +41,9 @@ jobs:
- name: Upload Results
if: ${{ matrix.python-version == env.LATEST_PY_VERSION }}
- uses: codecov/codecov-action at v5
+ uses: codecov/codecov-action at fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
files: ./coverage.xml
flags: unittests
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
-
- benchmark:
- needs: [tests]
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout at v5
-
- - name: Install uv
- uses: astral-sh/setup-uv at v7
- with:
- version: "0.9.*"
- enable-cache: true
- python-version: ${{ env.LATEST_PY_VERSION }}
-
- - name: Install dependencies
- run: |
- uv sync --group benchmark
-
- - name: Run Benchmark
- run: |
- uv run pytest tests/benchmarks.py --benchmark-only --benchmark-columns 'min, max, mean, median' --benchmark-sort 'min' --benchmark-json output.json
-
- - name: Store and Compare benchmark result
- uses: benchmark-action/github-action-benchmark at v1
- with:
- name: morecantile Benchmarks
- tool: 'pytest'
- output-file-path: output.json
- alert-threshold: '150%'
- comment-on-alert: true
- fail-on-alert: false
- # GitHub API token to make a commit comment
- github-token: ${{ secrets.GITHUB_TOKEN }}
- gh-pages-branch: 'gh-benchmarks'
- # Make a commit on `gh-pages` only if main
- auto-push: ${{ github.ref == 'refs/heads/main' }}
- benchmark-data-dir-path: dev/benchmarks
-
- publish:
- needs: [tests]
- runs-on: ubuntu-latest
- if: startsWith(github.event.ref, 'refs/tags') || github.event_name == 'release'
- steps:
- - uses: actions/checkout at v5
-
- - name: Install uv
- uses: astral-sh/setup-uv at v7
- with:
- version: "0.9.*"
- enable-cache: true
- python-version: ${{ env.LATEST_PY_VERSION }}
-
- - name: Install dependencies
- run: |
- uv sync --group deploy
-
- - name: Set tag version
- id: tag
- run: |
- echo "version=${GITHUB_REF#refs/*/}"
- echo "version=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
-
- - name: Set module version
- id: module
- run: |
- echo "version=$(uv run hatch --quiet version)" >> $GITHUB_OUTPUT
-
- - name: Build and publish
- if: ${{ steps.tag.outputs.version }} == ${{ steps.module.outputs.version}}
- env:
- HATCH_INDEX_USER: ${{ secrets.PYPI_USERNAME }}
- HATCH_INDEX_AUTH: ${{ secrets.PYPI_PASSWORD }}
- run: |
- uv run hatch build
- uv run hatch publish
\ No newline at end of file
=====================================
.github/workflows/deploy_mkdocs.yml
=====================================
@@ -11,16 +11,20 @@ on:
- 'CONTRIBUTING.md'
- 'docs/**'
+concurrency:
+ group: docs-gh-pages
+ cancel-in-progress: false
+
jobs:
build:
name: Deploy docs
runs-on: ubuntu-latest
steps:
- name: Checkout main
- uses: actions/checkout at v5
+ uses: actions/checkout at 3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install uv
- uses: astral-sh/setup-uv at v7
+ uses: astral-sh/setup-uv at bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
version: "0.9.*"
enable-cache: true
=====================================
.github/workflows/release.yml
=====================================
@@ -0,0 +1,73 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - '*'
+env:
+ LATEST_PY_VERSION: '3.14'
+
+jobs:
+ build:
+ name: Build dist
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
+ steps:
+ - uses: actions/checkout at 3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
+
+ - name: Install uv
+ uses: astral-sh/setup-uv at bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
+ with:
+ version: "0.9.*"
+ enable-cache: true
+ python-version: ${{ env.LATEST_PY_VERSION }}
+
+ - name: Install dependencies
+ run: |
+ uv sync --group deploy
+
+ - name: Set tag version
+ id: tag
+ run: |
+ echo "version=${GITHUB_REF#refs/*/}"
+ echo "version=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
+
+ - name: Set module version
+ id: module
+ run: |
+ echo "version=$(uv run hatch --quiet version)" >> $GITHUB_OUTPUT
+
+ - name: Check version match
+ run: |
+ if [ "${{ steps.tag.outputs.version }}" != "${{ steps.module.outputs.version }}" ]; then
+ echo "Tag version (${{ steps.tag.outputs.version }}) does not match module version (${{ steps.module.outputs.version }})"
+ exit 1
+ fi
+
+ - name: Build
+ run: |
+ uv run hatch build
+
+ - uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ with:
+ path: ./dist/
+
+ upload_pypi:
+ name: Upload release to PyPI
+ needs: [build]
+ runs-on: ubuntu-latest
+ environment:
+ # Note: this environment must be configured in the repo settings
+ name: pypi-release
+ url: https://pypi.org/p/morecantile
+ permissions:
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
+ steps:
+ - uses: actions/download-artifact at 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
+ with:
+ name: artifact
+ path: dist
+ merge-multiple: true
+
+ - name: Publish package distributions to PyPI
+ uses: pypa/gh-action-pypi-publish at dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
=====================================
.pre-commit-config.yaml
=====================================
@@ -1,18 +1,18 @@
repos:
- repo: https://github.com/abravalheri/validate-pyproject
- rev: v0.24
+ rev: '0.26'
hooks:
- id: validate-pyproject
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.15.0
+ rev: v0.16.7
hooks:
- id: ruff
args: ["--fix"]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.11.2
+ rev: v2.3.1
hooks:
- id: mypy
language_version: python
=====================================
CHANGES.md
=====================================
@@ -1,6 +1,10 @@
## Unreleased
+## 7.1.0 (2026-09-16)
+
+* add `matrix_to_geojson` method to `TileMatrixSet` class
+
## 7.0.3 (2026-02-05)
* add top-level export (`__all__`) (author @kylebarron, https://github.com/developmentseed/morecantile/pull/202)
@@ -445,6 +449,7 @@ tms._crs.to_epsg()
By default, it is set to `auto`, meaning that it will select the closest zoom level. User can set the strategy to `lower` or `upper` to select below or above zoom levels.
```python
import morecantile
+
tms = morecantile.tms.get("WebMercatorQuad")
# native resolution of zoom 7 is 1222.9924 m
@@ -528,9 +533,11 @@ with open("/tmp/mytms/MyCustomTmsEPSG3031.json", "w") as f:
```python
import os
+
os.environ["TILEMATRIXSET_DIRECTORY"] = "/tmp/mytms"
from morecantile import tms
+
assert "MyCustomTmsEPSG3031" in tms.list()
```
=====================================
morecantile/__init__.py
=====================================
@@ -8,7 +8,7 @@ Refs:
"""
-__version__ = "7.0.3"
+__version__ = "7.1.0"
from .commons import BoundingBox, Coords, Tile
from .defaults import TileMatrixSets, tms
=====================================
morecantile/models.py
=====================================
@@ -1473,8 +1473,7 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True, extra="ignore"):
stacklevel=1,
)
- if authority_code := feature_crs.to_authority(min_confidence=20):
- authority, code = authority_code
+ if feature_crs.to_authority(min_confidence=20):
feat.update(
{
"crs": {
@@ -1761,3 +1760,39 @@ class TileMatrixSet(BaseModel, arbitrary_types_allowed=True, extra="ignore"):
tiles.append(Tile(i, j, target_zoom))
return tiles
+
+ def matrix_to_geojson(
+ self,
+ level: int,
+ precision: int | None = None,
+ buffer: NumType | None = None,
+ geographic: bool = True,
+ geographic_crs: pyproj.CRS | None = None,
+ ) -> Iterator[dict]:
+ """Yield GeoJSON representation of the tile matrix set."""
+ matrix = self.matrix(level)
+
+ for y in range(0, matrix.matrixHeight):
+ cf = (
+ matrix.get_coalesce_factor(y)
+ if matrix.variableMatrixWidths is not None
+ else 1
+ )
+ for x in range(0, matrix.matrixWidth):
+ if cf != 1 and x % cf:
+ continue
+
+ feature = self.feature(
+ Tile(x, y, level),
+ projected=not geographic,
+ buffer=buffer,
+ precision=precision,
+ geographic_crs=geographic_crs,
+ )
+ feature["properties"] = {
+ "x": x,
+ "y": y,
+ "z": level,
+ }
+
+ yield feature
=====================================
morecantile/scripts/cli.py
=====================================
@@ -3,6 +3,7 @@
import json
import logging
import sys
+from typing import Any
import click
from pyproj import CRS
@@ -554,9 +555,8 @@ def tms_to_geojson( # noqa: C901
):
"""Print TMS document as GeoJSON."""
tms = morecantile.TileMatrixSet(**json.load(input))
- matrix = tms.matrix(level)
- dump_kwds = {"sort_keys": True}
+ dump_kwds: dict[str, Any] = {"sort_keys": True}
if indent:
dump_kwds["indent"] = indent
if compact:
@@ -566,39 +566,31 @@ def tms_to_geojson( # noqa: C901
col_xs = []
col_ys = []
- for y in range(0, matrix.matrixHeight):
- cf = (
- matrix.get_coalesce_factor(y)
- if matrix.variableMatrixWidths is not None
- else 1
- )
- for x in range(0, matrix.matrixWidth):
- if cf != 1 and x % cf:
- continue
-
- feature = tms.feature(
- (x, y, level),
- projected=projected,
- buffer=buffer,
- precision=precision,
- geographic_crs=CRS.from_user_input(crs) if crs else WGS84_CRS,
- )
- bbox = feature["bbox"]
- w, s, e, n = bbox
- col_xs.extend([w, e])
- col_ys.extend([s, n])
-
- if collect:
- features.append(feature)
- elif extents:
- click.echo(" ".join(map(str, bbox)))
- else:
- if seq:
- click.echo("\x1e")
- if output_mode == "bbox":
- click.echo(json.dumps(bbox, **dump_kwds))
- elif output_mode == "feature":
- click.echo(json.dumps(feature, **dump_kwds))
+ geographic_crs = CRS.from_user_input(crs) if crs else WGS84_CRS
+
+ for feature in tms.matrix_to_geojson(
+ level,
+ precision=precision,
+ buffer=buffer,
+ geographic=not projected,
+ geographic_crs=geographic_crs,
+ ):
+ bbox = feature["bbox"]
+ w, s, e, n = bbox
+ col_xs.extend([w, e])
+ col_ys.extend([s, n])
+
+ if collect:
+ features.append(feature)
+ elif extents:
+ click.echo(" ".join(map(str, bbox)))
+ else:
+ if seq:
+ click.echo("\x1e")
+ if output_mode == "bbox":
+ click.echo(json.dumps(bbox, **dump_kwds))
+ elif output_mode == "feature":
+ click.echo(json.dumps(feature, **dump_kwds))
if collect and features:
bbox = [min(col_xs), min(col_ys), max(col_xs), max(col_ys)]
=====================================
pyproject.toml
=====================================
@@ -119,7 +119,7 @@ filterwarnings = [
]
[tool.bumpversion]
-current_version = "7.0.3"
+current_version = "7.1.0"
search = "{current_version}"
replace = "{new_version}"
=====================================
tests/test_models.py
=====================================
@@ -939,3 +939,14 @@ def test_bbox_bottom_left():
assert tms._ul(Tile(x=1, y=1, z=1)) == Coords(x=0.0, y=100000.0)
assert tms._lr(Tile(x=1, y=1, z=1)) == Coords(x=100000.0, y=0)
+
+
+ at pytest.mark.parametrize("tilematrixset", morecantile.tms.list())
+def test_to_geojson(tilematrixset):
+ """Test to_geojson method."""
+ t = morecantile.tms.get(tilematrixset)
+ geojson = list(t.matrix_to_geojson(level=t.minzoom))
+ assert geojson[0]["type"] == "Feature"
+
+ geojson = list(t.matrix_to_geojson(level=t.minzoom, geographic=False))
+ assert geojson[0]["type"] == "Feature"
=====================================
tests/test_morecantile.py
=====================================
@@ -452,8 +452,8 @@ def test_tiles_when_tms_bounds_and_provided_bounds_cross_antimeridian(
# antimeridian e.g. min(119.2, -158.605) clamps to much larger area. Now
# that we check to see if lons contain antimeridian, we build tiles that
# actually overlap the provided bounds to tiles.
- assert tms.bbox == tms_bbox
- for a, b in zip(tms.bbox, tms_bbox):
+ # assert tms.bbox == tms_bbox
+ for a, b in zip(tms.bbox, tms_bbox, strict=True):
assert round(a - b, 6) == 0
assert len(list(tms.tiles(*bounds, zooms=11))) == expected
=====================================
uv.lock
=====================================
The diff for this file was not included because it is too large.
View it on GitLab: https://salsa.debian.org/debian-gis-team/morecantile/-/commit/d5e28bfde000f23d2231ece2eb7576bbd8f4a292
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/morecantile/-/commit/d5e28bfde000f23d2231ece2eb7576bbd8f4a292
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20260916/d1eaaad6/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list