[Git][debian-gis-team/eodag][master] 5 commits: New upstream version 4.7.1+ds
Antonio Valentino (@antonio.valentino)
gitlab at salsa.debian.org
Thu Aug 20 18:08:17 BST 2026
Antonio Valentino pushed to branch master at Debian GIS Project / eodag
Commits:
048acf2a by Antonio Valentino at 2026-08-20T14:29:36+00:00
New upstream version 4.7.1+ds
- - - - -
366e69d4 by Antonio Valentino at 2026-08-20T14:29:44+00:00
Update upstream source from tag 'upstream/4.7.1+ds'
Update to upstream version '4.7.1+ds'
with Debian dir 0535e68bc7dd5429f72c89f80c5a5e4ff1386a1d
- - - - -
85463608 by Antonio Valentino at 2026-08-20T14:30:36+00:00
New upstream release
- - - - -
97f15138 by Antonio Valentino at 2026-08-20T14:34:14+00:00
Refresh all patches
- - - - -
08b4b9c3 by Antonio Valentino at 2026-08-20T14:35:31+00:00
Set distribution to unstable
- - - - -
23 changed files:
- .github/workflows/benchmark.yml
- .github/workflows/changelog.yml
- .github/workflows/deploy.yml
- .github/workflows/fetch.yml
- .github/workflows/publish.yml
- .github/workflows/test.yml
- CHANGES.rst
- debian/changelog
- debian/patches/0001-System-importlib.metadata.patch
- docs/providers.rst
- eodag/api/product/_assets.py
- eodag/plugins/search/eumetsat_ds.py
- eodag/plugins/search/qssearch.py
- eodag/resources/ext_collections.json
- eodag/resources/ext_product_types.json
- eodag/utils/logging.py
- eodag/utils/s3.py
- pyproject.toml
- tests/context.py
- tests/test_benchmark.py
- + tests/units/test_assets.py
- tests/units/test_utils.py
- tox.ini
Changes:
=====================================
.github/workflows/benchmark.yml
=====================================
@@ -19,11 +19,13 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
+ cache-dependency-glob: |
+ pyproject.toml
+ tox.ini
- name: Run benchmark on develop and current ref, then compare
shell: bash
run: |
=====================================
.github/workflows/changelog.yml
=====================================
@@ -16,11 +16,10 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
- name: Install python-semantic-release and packaging in venv
run: |
uv venv
=====================================
.github/workflows/deploy.yml
=====================================
@@ -22,11 +22,10 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
- name: Install python-semantic-release in venv
run: |
uv venv
=====================================
.github/workflows/fetch.yml
=====================================
@@ -22,11 +22,10 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
- name: Install eodag in venv
run: |
uv venv
@@ -168,11 +167,10 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
- name: Install eodag v3 in venv
run: |
uv venv
=====================================
.github/workflows/publish.yml
=====================================
@@ -19,11 +19,13 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
+ cache-dependency-glob: |
+ pyproject.toml
+ tox.ini
- name: Check that the current version isn't already on PyPi
run: |
if [ "$(./utils/get_pypi_latest_version.sh)" != "$(git describe --tags)" ]
=====================================
.github/workflows/test.yml
=====================================
@@ -20,11 +20,13 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
+ cache-dependency-glob: |
+ pyproject.toml
+ tox.ini
- name: Run linters with tox
run: uvx --python 3.9 --with tox-uv tox -e linters
@@ -42,11 +44,13 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
+ cache-dependency-glob: |
+ pyproject.toml
+ tox.ini
- name: Test with tox
run: uvx --python ${{ matrix.python-version }} --with tox-uv --with tox-gh-actions tox
- name: Upload Unit Test Results
@@ -193,11 +197,13 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
+ cache-dependency-glob: |
+ pyproject.toml
+ tox.ini
- name: Install pandoc
run: |
curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | grep -o "https.*amd64.deb" | wget -O pandoc.deb -qi -
@@ -215,10 +221,12 @@ jobs:
# Get history and tags for SCM versioning to work
fetch-depth: 0
- name: Install the latest version of uv with cache enabled
- uses: astral-sh/setup-uv at v3
+ uses: astral-sh/setup-uv at v9.0.0
with:
version: "latest"
enable-cache: true
- cache-dependency-glob: ""
+ cache-dependency-glob: |
+ pyproject.toml
+ tox.ini
- name: Testing with tox and sphinx (to have rst2html.py utility available)
run: uvx --with tox-uv --with sphinx tox -e pypi
=====================================
CHANGES.rst
=====================================
@@ -3,6 +3,51 @@ Release history
===============
+v4.7.1 (2026-08-20)
+===================
+
+Performance Improvements
+------------------------
+
+* **core**: Optimize AssetsDict batch updates (`#2314`_, `4783588`_)
+
+.. _#2314: https://github.com/CS-SI/eodag/pull/2314
+.. _4783588: https://github.com/CS-SI/eodag/commit/4783588f865255124671af8e2fec45ffbfaac3d5
+
+
+v4.7.0 (2026-08-19)
+===================
+
+Features
+--------
+
+* **core**: Sort assets and remove private fields (`#2309`_, `3e97a4d`_)
+
+Bug Fixes
+---------
+
+* **logging**: Logs handling through tqdm (`#1640`_, `48c3891`_)
+
+Continuous Integration
+----------------------
+
+* Tox and uv conf cleanup (`#2300`_, `8f6e915`_)
+
+Documentation
+-------------
+
+* Update provider registration introduction (`#2302`_, `cb4e4d6`_)
+
+.. _#1640: https://github.com/CS-SI/eodag/pull/1640
+.. _#2300: https://github.com/CS-SI/eodag/pull/2300
+.. _#2302: https://github.com/CS-SI/eodag/pull/2302
+.. _#2309: https://github.com/CS-SI/eodag/pull/2309
+.. _3e97a4d: https://github.com/CS-SI/eodag/commit/3e97a4d4fb7169392e6892707377d47b7243286d
+.. _48c3891: https://github.com/CS-SI/eodag/commit/48c38912bb5d24cae599769951db7e4550b223b1
+.. _8f6e915: https://github.com/CS-SI/eodag/commit/8f6e915d831f73effabe139ca828f89f718c3008
+.. _cb4e4d6: https://github.com/CS-SI/eodag/commit/cb4e4d64b23173289eefafddaa740bbfaff4a7ee
+
+
v4.6.0 (2026-08-11)
===================
=====================================
debian/changelog
=====================================
@@ -1,3 +1,11 @@
+eodag (4.7.1+ds-1) unstable; urgency=medium
+
+ * New upstream release.
+ * debian/patches:
+ - Refresh all patches.
+
+ -- Antonio Valentino <antonio.valentino at tiscali.it> Thu, 20 Aug 2026 14:35:08 +0000
+
eodag (4.6.0+ds-1) unstable; urgency=medium
* New upstream release.
=====================================
debian/patches/0001-System-importlib.metadata.patch
=====================================
@@ -65,7 +65,7 @@ index 5fd4a7d..c4cc0d3 100644
"""Return provider config paths exposed by an external plugin distribution."""
config_paths: list[pathlib.Path] = []
diff --git a/pyproject.toml b/pyproject.toml
-index 8369c34..7448ee7 100644
+index ba93069..bc1c287 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,7 +39,6 @@ dependencies = [
=====================================
docs/providers.rst
=====================================
@@ -10,7 +10,8 @@ This section introduces the featured providers that are already integrated, so y
easily start searching, accessing, and downloading products.
Some providers are completely open, while others require an account to access their data.
-If credentials are needed, check the :doc:`registration guide <providers>` for details.
+Check provider ``Registration info`` in this page to see if credentials are expected and how to get
+them.
.. admonition:: EODAG is not limited to the providers listed here
:class: note
=====================================
eodag/api/product/_assets.py
=====================================
@@ -21,6 +21,8 @@ import re
from collections import UserDict
from typing import TYPE_CHECKING, Any, Optional
+from typing_extensions import override
+
from eodag.utils.exceptions import NotAvailableError
from eodag.utils.repr import dict_to_html_table
@@ -60,12 +62,50 @@ class AssetsDict(UserDict):
self.product = product
super(AssetsDict, self).__init__(*args, **kwargs)
- def update(self, data: dict[str, Any]) -> None: # type: ignore
- """Update assets"""
- super().update(data)
-
def __setitem__(self, key: str, value: dict[str, Any]) -> None:
- super().__setitem__(key, Asset(self.product, key, value))
+ super().__setitem__(key, self._make_asset(key, value))
+ self.sort()
+
+ def _make_asset(self, key: str, value: dict[str, Any]) -> Asset:
+ """Build the :class:`Asset` to store for the given key/value pair.
+
+ Subclasses (e.g. eodag_cube) can override this to use an extended
+ :class:`Asset` subclass without duplicating the sorting and other
+ logic implemented in :meth:`__setitem__`/:meth:`update`.
+
+ :param key: Asset key
+ :param value: Already-validated asset dictionary
+ :returns: The :class:`Asset` instance to store
+ """
+ return Asset(self.product, key, value)
+
+ @override
+ def update(self, *args: Any, **kwargs: Any) -> None:
+ """Used to self update with external value"""
+ incoming = dict(*args, **kwargs)
+
+ if not incoming:
+ return
+
+ if type(self).__setitem__ is not AssetsDict.__setitem__:
+ # Preserve custom __setitem__ behavior implemented by subclasses.
+ super().update(incoming)
+ else:
+ # Avoid sorting after every insertion in the base implementation.
+ for key, value in incoming.items():
+ self.data[key] = self._make_asset(key, value)
+ self.sort()
+
+ def sort(self):
+ """Used to self sort"""
+ sorted_assets = {}
+ for key in sorted(self.data):
+ asset = self.data[key]
+ # delete private asset fields (fields starting with '_')
+ for private_field in [k for k in asset if k[0] == "_"]:
+ del asset[private_field]
+ sorted_assets[key] = asset
+ self.data = sorted_assets
def as_dict(self) -> dict[str, Any]:
"""Builds a representation of AssetsDict to enable its serialization
@@ -171,7 +211,8 @@ class Asset(UserDict):
def __init__(self, product: EOProduct, key: str, *args: Any, **kwargs: Any) -> None:
self.product = product
self.key = key
- super(Asset, self).__init__(*args, **kwargs)
+ # Faster than UserDict.__init__, which goes through MutableMapping.update()
+ self.data = dict(*args, **kwargs)
def as_dict(self) -> dict[str, Any]:
"""Builds a representation of Asset to enable its serialization
=====================================
eodag/plugins/search/eumetsat_ds.py
=====================================
@@ -47,14 +47,13 @@ class EumetsatDsSearch(QueryStringSearch):
for index in range(0, len(processed_results)):
result = processed_results[index]
if hasattr(result, "assets"):
- for name, asset in result.assets.items():
+ for asset in result.assets.values():
if "type" in asset:
asset["eumesat_ds:type"] = asset["type"]
del asset["type"]
if "mediaType" in asset:
asset["type"] = asset["mediaType"]
del asset["mediaType"]
- result.assets[name] = asset
processed_results[index] = result
return processed_results
=====================================
eodag/plugins/search/qssearch.py
=====================================
@@ -1307,9 +1307,9 @@ class QueryStringSearch(Search):
product = EOProduct(self.provider, properties, **product_kwargs)
additional_assets = self.get_assets_from_mapping(result)
- product.assets.update(additional_assets)
# move assets from properties to product's attr, normalize keys & roles
+ normalized_assets: dict[str, Any] = {}
for key, asset in product.properties.pop("assets", {}).items():
url = asset.get("href", "")
norm_key, roles = product.driver.guess_asset_key_and_roles(
@@ -1319,13 +1319,13 @@ class QueryStringSearch(Search):
if norm_key is not None:
asset["title"] = norm_key
asset["roles"] = roles
- product.assets[norm_key] = asset
+ normalized_assets[norm_key] = asset
else:
asset["title"] = asset.get("title", key)
- product.assets[key] = asset
+ normalized_assets[key] = asset
- # sort assets
- product.assets.data = dict(sorted(product.assets.data.items()))
+ # batch-update once to avoid assets sort and clean up on every update
+ product.assets.update({**additional_assets, **normalized_assets})
product._normalize_bands()
products.append(product)
return products
=====================================
eodag/resources/ext_collections.json
=====================================
The diff for this file was not included because it is too large.
=====================================
eodag/resources/ext_product_types.json
=====================================
The diff for this file was not included because it is too large.
=====================================
eodag/utils/logging.py
=====================================
@@ -18,11 +18,31 @@
from __future__ import annotations
import logging.config
-from typing import Optional
+from typing import Any, Optional
disable_tqdm = False
+class TqdmLoggingHandler(logging.StreamHandler):
+ """Logging handler writing through :func:`tqdm.write` to avoid breaking progress bars"""
+
+ def emit(self, record: logging.LogRecord) -> None:
+ """Emit a record using ``tqdm.write()`` if progress bars are enabled
+
+ :param record: The log record to emit
+ """
+ if disable_tqdm:
+ super().emit(record)
+ return
+ try:
+ from tqdm.auto import tqdm
+
+ tqdm.write(self.format(record), file=self.stream, end=self.terminator)
+ self.flush()
+ except Exception:
+ self.handleError(record)
+
+
def setup_logging(verbose: int, no_progress_bar: bool = False) -> None:
"""Define logging level
@@ -45,10 +65,10 @@ def setup_logging(verbose: int, no_progress_bar: bool = False) -> None:
level = "DEBUG" if verbose == 3 else "INFO"
- handlers = {
+ handlers: dict[str, dict[str, Any]] = {
"console": {
"level": level,
- "class": "logging.StreamHandler",
+ "class": "eodag.utils.logging.TqdmLoggingHandler",
"formatter": "standard",
},
"null": {"level": level, "class": "logging.NullHandler"},
=====================================
eodag/utils/s3.py
=====================================
@@ -605,12 +605,12 @@ def update_assets_from_s3(
assets_data[key] = asset_data
- for key in assets_data:
- if key not in product.assets:
- product.assets[key] = assets_data[key]
-
- # sort assets
- product.assets.data = dict(sorted(product.assets.data.items()))
+ new_assets = {
+ key: asset_data
+ for key, asset_data in assets_data.items()
+ if key not in product.assets
+ }
+ product.assets.update(new_assets)
# update driver
product.driver = product.get_driver()
=====================================
pyproject.toml
=====================================
@@ -211,7 +211,7 @@ include = ["eodag*"]
"*" = ["LICENSE", "NOTICE", "py.typed"]
[tool.setuptools_scm]
-fallback_version = "4.6.1.dev0"
+fallback_version = "4.7.2.dev0"
[tool.isort]
multi_line_output = 3
=====================================
tests/context.py
=====================================
@@ -28,6 +28,7 @@ from unittest import mock
from eodag import EODataAccessGateway, api, config, setup_logging
from eodag.api.core import DEFAULT_LIMIT, DEFAULT_MAX_LIMIT
from eodag.api.product import EOProduct
+from eodag.api.product._assets import Asset, AssetsDict
from eodag.api.product.drivers import DRIVERS
from eodag.api.product.drivers.generic import GenericDriver
from eodag.api.product.drivers.sentinel1 import Sentinel1Driver
=====================================
tests/test_benchmark.py
=====================================
@@ -21,7 +21,8 @@ import subprocess
import sys
from tempfile import TemporaryDirectory
-from tests import test_cli
+from tests import EODagTestBase, test_cli
+from tests.context import EOProduct
from tests.integration import test_core_search_results
from tests.units import test_stac_reader
from tests.utils import write_eodag_conf_with_fake_credentials
@@ -144,3 +145,36 @@ def test_benchmark_stac_reader_fetch_recursive(benchmark):
"test_stac_reader_fetch_root_recursive",
)
)
+
+
+def test_benchmark_eoproduct_instantiation(benchmark):
+ test_case = EODagTestBase()
+ test_case.setUp()
+ try:
+ benchmark(
+ lambda: EOProduct(
+ test_case.provider,
+ test_case.eoproduct_props,
+ collection=test_case.collection,
+ )
+ )
+ finally:
+ test_case.tearDown()
+
+
+def test_benchmark_eoproduct_assets_population(benchmark):
+ test_case = EODagTestBase()
+ test_case.setUp()
+ try:
+ product = test_case._dummy_product()
+ assets = {
+ f"band{i}": {"href": f"http://example.com/band{i}.tif"} for i in range(20)
+ }
+
+ def _populate_assets():
+ product.assets.update(assets)
+ return len(product.assets)
+
+ benchmark(_populate_assets)
+ finally:
+ test_case.tearDown()
=====================================
tests/units/test_assets.py
=====================================
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+# Copyright 2026, CS GROUP - France, https://www.csgroup.eu/
+#
+# This file is part of EODAG project
+# https://www.github.com/CS-SI/EODAG
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import unittest
+
+from tests.context import Asset, AssetsDict, mock
+
+
+class CustomAsset(Asset):
+ pass
+
+
+class CustomAssetsDict(AssetsDict):
+ def _make_asset(self, key, value):
+ return CustomAsset(self.product, key, value)
+
+
+class HookedAssetsDict(AssetsDict):
+ def __init__(self, product):
+ self.setitem_keys = []
+ super().__init__(product)
+
+ def __setitem__(self, key, value):
+ self.setitem_keys.append(key)
+ super().__setitem__(key, value)
+
+
+class TestAssetsDict(unittest.TestCase):
+ @mock.patch.object(AssetsDict, "sort")
+ def test_update_and_setitem_use_asset_factory_override(self, mock_sort):
+ """Use the overridden asset factory and sort assets after updates."""
+ assets = CustomAssetsDict(object())
+
+ assets.update(
+ {
+ "z": {"href": "z"},
+ "a": {"href": "a"},
+ }
+ )
+ assets["m"] = {"href": "m"}
+
+ mock_sort.assert_called()
+
+ self.assertTrue(
+ all(isinstance(asset, CustomAsset) for asset in assets.values())
+ )
+
+ def test_update_preserves_overridden_setitem(self):
+ """Use an overridden __setitem__ when updating a subclass."""
+ assets = HookedAssetsDict(object())
+
+ assets.update({"z": {"href": "z"}, "a": {"href": "a"}})
+
+ self.assertEqual(assets.setitem_keys, ["z", "a"])
+
+ def test_update_and_setitem_sort_assets_and_remove_private_fields(self):
+ """Sort assets and remove private fields after updates."""
+ assets = AssetsDict(object())
+
+ assets.update(
+ {
+ "z": {"href": "z", "_internal": "remove"},
+ "a": {"href": "a", "_internal": "remove"},
+ }
+ )
+ assets["m"] = {"href": "m", "_internal": "remove"}
+
+ self.assertEqual(list(assets), ["a", "m", "z"])
+ self.assertDictEqual(
+ {key: dict(asset) for key, asset in assets.items()},
+ {
+ "a": {"href": "a"},
+ "m": {"href": "m"},
+ "z": {"href": "z"},
+ },
+ )
=====================================
tests/units/test_utils.py
=====================================
@@ -34,6 +34,7 @@ from requests.exceptions import RequestException
from shapely.geometry import Point, Polygon
from eodag.utils import get_geometry_from_ecmwf_area, get_geometry_from_ecmwf_feature
+from eodag.utils.logging import TqdmLoggingHandler
from tests.context import (
HTTP_REQ_TIMEOUT,
USER_AGENT,
@@ -203,6 +204,56 @@ class TestUtils(unittest.TestCase):
bar(1)
self.assertEqual(tqdm_out.getvalue(), "")
+ @mock.patch("tqdm.auto.tqdm.write")
+ def test_tqdm_logging_handler_uses_tqdm_write(self, tqdm_write):
+ """Test logging through tqdm preserves the progress bar output."""
+ handler = TqdmLoggingHandler(stream=StringIO())
+ handler.setFormatter(logging.Formatter("%(message)s"))
+ record = logging.LogRecord(
+ name="eodag",
+ level=logging.INFO,
+ pathname=__file__,
+ lineno=1,
+ msg="log message",
+ args=(),
+ exc_info=None,
+ )
+
+ handler.emit(record)
+
+ tqdm_write.assert_called_once_with(
+ "log message", file=handler.stream, end=handler.terminator
+ )
+
+ @mock.patch("tqdm.auto.tqdm.write")
+ def test_tqdm_logging_handler_falls_back_to_stream(self, tqdm_write):
+ """Test disabled progress bars use the regular stream handler."""
+ setup_logging(verbose=2, no_progress_bar=True)
+ output = StringIO()
+ handler = TqdmLoggingHandler(stream=output)
+ handler.setFormatter(logging.Formatter("%(message)s"))
+ record = logging.LogRecord(
+ name="eodag",
+ level=logging.INFO,
+ pathname=__file__,
+ lineno=1,
+ msg="log message",
+ args=(),
+ exc_info=None,
+ )
+
+ handler.emit(record)
+
+ self.assertEqual(output.getvalue(), "log message\n")
+ tqdm_write.assert_not_called()
+
+ def test_setup_logging_installs_tqdm_handler(self):
+ """Test console logging uses the handler that cooperates with tqdm."""
+ setup_logging(verbose=2)
+
+ logger = logging.getLogger("eodag")
+ self.assertIsInstance(logger.handlers[0], TqdmLoggingHandler)
+
def test_merge_mappings(self):
"""Test merge_mappings merges configuration mappings correctly."""
=====================================
tox.ini
=====================================
@@ -16,6 +16,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
[tox]
+requires = tox-uv
envlist = py39, py310, py311, py312, py313, py314, benchmark, docs, pypi, linters
skipdist = true
@@ -30,8 +31,6 @@ python =
3.14: py314
[testenv]
-install_command = uv pip install --upgrade {opts} {packages}
-
commands =
python -c "import os; os.makedirs('test-reports', exist_ok=True)"
pytest -v --instafail \
@@ -88,7 +87,6 @@ skip_install = true
deps =
build
twine
- uv
commands =
# build package to be checked
python -m build --installer uv
View it on GitLab: https://salsa.debian.org/debian-gis-team/eodag/-/compare/8a6197d2954fe0e547a329bd7d69c19330af1476...08b4b9c32ccea34a95e035e95a681f122f967040
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/eodag/-/compare/8a6197d2954fe0e547a329bd7d69c19330af1476...08b4b9c32ccea34a95e035e95a681f122f967040
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/20260820/da0792bd/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list