diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..87db8ac6 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,18 @@ +name: Publish to PyPI + +on: + push: + tags: + - "v*" + +jobs: + publish: + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v5 + - run: uv build + - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/Dockerfile b/Dockerfile index 9257ee09..779a3e97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN groupadd --system eo && useradd --system --gid eo --create-home eo WORKDIR /app COPY pyproject.toml uv.lock .python-version ./ -COPY src/ src/ +COPY climate_api/ climate_api/ RUN uv sync --frozen --no-dev diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..2a0923cc --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2004-2025, University of Oslo +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile index 7dd4d97e..63b8bc00 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ run: openapi ## Start the app with uvicorn lint: ## Check linting, formatting, and types (no autofix) uv run ruff check . uv run ruff format --check . - uv run mypy src/ + uv run mypy climate_api/ uv run pyright fix: ## Autofix ruff lint and format issues @@ -24,7 +24,7 @@ test: ## Run tests with pytest openapi: ## Generate pygeoapi OpenAPI spec @set -a && . ./.env && set +a && \ - PYTHONPATH="$(PWD)/src" uv run python -c "from climate_api.publications.services import ensure_pygeoapi_base_config; ensure_pygeoapi_base_config()" + uv run python -c "from climate_api.publications.services import ensure_pygeoapi_base_config; ensure_pygeoapi_base_config()" start: openapi ## Start the Docker stack (builds images first) docker compose up --build diff --git a/README.md b/README.md index 9797e950..88753223 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Install dependencies (requires [uv](https://docs.astral.sh/uv/)): uv sync ``` + Copy `.env.example` to `.env` and adjust values as needed. Environment variables are loaded automatically from `.env` at runtime. See `.env.example` for the full list of available options. Start the app: @@ -110,7 +111,7 @@ else: The OGC API is served by pygeoapi, mounted at `/ogcapi`. Its configuration is generated dynamically from published artifacts and written to the resolved runtime data directory (for Docker: `/app/data/pygeoapi/pygeoapi-config.yml`). -The base configuration is bundled with the package at `src/climate_api/data/pygeoapi/base.yml` and does not need to be copied or managed separately. +The base configuration is bundled with the package at `climate_api/data/pygeoapi/base.yml` and does not need to be copied or managed separately. To validate the configuration manually: diff --git a/src/climate_api/__init__.py b/climate_api/__init__.py similarity index 100% rename from src/climate_api/__init__.py rename to climate_api/__init__.py diff --git a/src/climate_api/cli.py b/climate_api/cli.py similarity index 100% rename from src/climate_api/cli.py rename to climate_api/cli.py diff --git a/src/climate_api/client.py b/climate_api/client.py similarity index 100% rename from src/climate_api/client.py rename to climate_api/client.py diff --git a/src/climate_api/config.py b/climate_api/config.py similarity index 100% rename from src/climate_api/config.py rename to climate_api/config.py diff --git a/src/climate_api/data/datasets/chirps3.yaml b/climate_api/data/datasets/chirps3.yaml similarity index 100% rename from src/climate_api/data/datasets/chirps3.yaml rename to climate_api/data/datasets/chirps3.yaml diff --git a/src/climate_api/data/datasets/era5_land.yaml b/climate_api/data/datasets/era5_land.yaml similarity index 100% rename from src/climate_api/data/datasets/era5_land.yaml rename to climate_api/data/datasets/era5_land.yaml diff --git a/src/climate_api/data/datasets/worldpop.yaml b/climate_api/data/datasets/worldpop.yaml similarity index 100% rename from src/climate_api/data/datasets/worldpop.yaml rename to climate_api/data/datasets/worldpop.yaml diff --git a/src/climate_api/data/pygeoapi/base.yml b/climate_api/data/pygeoapi/base.yml similarity index 100% rename from src/climate_api/data/pygeoapi/base.yml rename to climate_api/data/pygeoapi/base.yml diff --git a/src/climate_api/data_accessor/__init__.py b/climate_api/data_accessor/__init__.py similarity index 100% rename from src/climate_api/data_accessor/__init__.py rename to climate_api/data_accessor/__init__.py diff --git a/src/climate_api/data_accessor/routes.py b/climate_api/data_accessor/routes.py similarity index 100% rename from src/climate_api/data_accessor/routes.py rename to climate_api/data_accessor/routes.py diff --git a/src/climate_api/data_accessor/services/__init__.py b/climate_api/data_accessor/services/__init__.py similarity index 100% rename from src/climate_api/data_accessor/services/__init__.py rename to climate_api/data_accessor/services/__init__.py diff --git a/src/climate_api/data_accessor/services/accessor.py b/climate_api/data_accessor/services/accessor.py similarity index 100% rename from src/climate_api/data_accessor/services/accessor.py rename to climate_api/data_accessor/services/accessor.py diff --git a/src/climate_api/data_manager/__init__.py b/climate_api/data_manager/__init__.py similarity index 100% rename from src/climate_api/data_manager/__init__.py rename to climate_api/data_manager/__init__.py diff --git a/src/climate_api/data_manager/routes.py b/climate_api/data_manager/routes.py similarity index 100% rename from src/climate_api/data_manager/routes.py rename to climate_api/data_manager/routes.py diff --git a/src/climate_api/data_manager/services/__init__.py b/climate_api/data_manager/services/__init__.py similarity index 100% rename from src/climate_api/data_manager/services/__init__.py rename to climate_api/data_manager/services/__init__.py diff --git a/src/climate_api/data_manager/services/downloader.py b/climate_api/data_manager/services/downloader.py similarity index 100% rename from src/climate_api/data_manager/services/downloader.py rename to climate_api/data_manager/services/downloader.py diff --git a/src/climate_api/data_manager/services/utils.py b/climate_api/data_manager/services/utils.py similarity index 100% rename from src/climate_api/data_manager/services/utils.py rename to climate_api/data_manager/services/utils.py diff --git a/src/climate_api/data_registry/__init__.py b/climate_api/data_registry/__init__.py similarity index 100% rename from src/climate_api/data_registry/__init__.py rename to climate_api/data_registry/__init__.py diff --git a/src/climate_api/data_registry/routes.py b/climate_api/data_registry/routes.py similarity index 100% rename from src/climate_api/data_registry/routes.py rename to climate_api/data_registry/routes.py diff --git a/src/climate_api/data_registry/services/__init__.py b/climate_api/data_registry/services/__init__.py similarity index 100% rename from src/climate_api/data_registry/services/__init__.py rename to climate_api/data_registry/services/__init__.py diff --git a/src/climate_api/data_registry/services/datasets.py b/climate_api/data_registry/services/datasets.py similarity index 100% rename from src/climate_api/data_registry/services/datasets.py rename to climate_api/data_registry/services/datasets.py diff --git a/src/climate_api/extents/__init__.py b/climate_api/extents/__init__.py similarity index 100% rename from src/climate_api/extents/__init__.py rename to climate_api/extents/__init__.py diff --git a/src/climate_api/extents/routes.py b/climate_api/extents/routes.py similarity index 100% rename from src/climate_api/extents/routes.py rename to climate_api/extents/routes.py diff --git a/src/climate_api/extents/schemas.py b/climate_api/extents/schemas.py similarity index 100% rename from src/climate_api/extents/schemas.py rename to climate_api/extents/schemas.py diff --git a/src/climate_api/extents/services.py b/climate_api/extents/services.py similarity index 100% rename from src/climate_api/extents/services.py rename to climate_api/extents/services.py diff --git a/src/climate_api/ingestions/__init__.py b/climate_api/ingestions/__init__.py similarity index 100% rename from src/climate_api/ingestions/__init__.py rename to climate_api/ingestions/__init__.py diff --git a/src/climate_api/ingestions/routes.py b/climate_api/ingestions/routes.py similarity index 100% rename from src/climate_api/ingestions/routes.py rename to climate_api/ingestions/routes.py diff --git a/src/climate_api/ingestions/schemas.py b/climate_api/ingestions/schemas.py similarity index 100% rename from src/climate_api/ingestions/schemas.py rename to climate_api/ingestions/schemas.py diff --git a/src/climate_api/ingestions/services.py b/climate_api/ingestions/services.py similarity index 100% rename from src/climate_api/ingestions/services.py rename to climate_api/ingestions/services.py diff --git a/src/climate_api/ingestions/sync_engine.py b/climate_api/ingestions/sync_engine.py similarity index 100% rename from src/climate_api/ingestions/sync_engine.py rename to climate_api/ingestions/sync_engine.py diff --git a/src/climate_api/main.py b/climate_api/main.py similarity index 100% rename from src/climate_api/main.py rename to climate_api/main.py diff --git a/src/climate_api/providers/__init__.py b/climate_api/providers/__init__.py similarity index 100% rename from src/climate_api/providers/__init__.py rename to climate_api/providers/__init__.py diff --git a/src/climate_api/providers/availability.py b/climate_api/providers/availability.py similarity index 100% rename from src/climate_api/providers/availability.py rename to climate_api/providers/availability.py diff --git a/src/climate_api/publications/__init__.py b/climate_api/publications/__init__.py similarity index 100% rename from src/climate_api/publications/__init__.py rename to climate_api/publications/__init__.py diff --git a/src/climate_api/publications/services.py b/climate_api/publications/services.py similarity index 100% rename from src/climate_api/publications/services.py rename to climate_api/publications/services.py diff --git a/src/climate_api/pygeoapi_app.py b/climate_api/pygeoapi_app.py similarity index 100% rename from src/climate_api/pygeoapi_app.py rename to climate_api/pygeoapi_app.py diff --git a/src/climate_api/shared/__init__.py b/climate_api/shared/__init__.py similarity index 100% rename from src/climate_api/shared/__init__.py rename to climate_api/shared/__init__.py diff --git a/src/climate_api/shared/time.py b/climate_api/shared/time.py similarity index 100% rename from src/climate_api/shared/time.py rename to climate_api/shared/time.py diff --git a/src/climate_api/stac/__init__.py b/climate_api/stac/__init__.py similarity index 100% rename from src/climate_api/stac/__init__.py rename to climate_api/stac/__init__.py diff --git a/src/climate_api/stac/routes.py b/climate_api/stac/routes.py similarity index 100% rename from src/climate_api/stac/routes.py rename to climate_api/stac/routes.py diff --git a/src/climate_api/stac/schemas.py b/climate_api/stac/schemas.py similarity index 100% rename from src/climate_api/stac/schemas.py rename to climate_api/stac/schemas.py diff --git a/src/climate_api/stac/services.py b/climate_api/stac/services.py similarity index 100% rename from src/climate_api/stac/services.py rename to climate_api/stac/services.py diff --git a/src/climate_api/startup.py b/climate_api/startup.py similarity index 100% rename from src/climate_api/startup.py rename to climate_api/startup.py diff --git a/src/climate_api/system/__init__.py b/climate_api/system/__init__.py similarity index 100% rename from src/climate_api/system/__init__.py rename to climate_api/system/__init__.py diff --git a/src/climate_api/system/routes.py b/climate_api/system/routes.py similarity index 100% rename from src/climate_api/system/routes.py rename to climate_api/system/routes.py diff --git a/src/climate_api/system/schemas.py b/climate_api/system/schemas.py similarity index 100% rename from src/climate_api/system/schemas.py rename to climate_api/system/schemas.py diff --git a/src/climate_api/system/templates.py b/climate_api/system/templates.py similarity index 100% rename from src/climate_api/system/templates.py rename to climate_api/system/templates.py diff --git a/src/climate_api/templates/landing_page.html b/climate_api/templates/landing_page.html similarity index 100% rename from src/climate_api/templates/landing_page.html rename to climate_api/templates/landing_page.html diff --git a/pyproject.toml b/pyproject.toml index df4b916b..1e4e9a03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,11 +2,24 @@ requires = ["uv_build>=0.9.0"] build-backend = "uv_build" +[tool.uv.build-backend] +module-root = "" + [project] name = "climate-api" version = "0.1.0a1" requires-python = ">=3.13" -description = "Climate and Earth Observation data API for DHIS2" +description = "Climate and Earth Observation data API" +license = { text = "BSD-3-Clause" } +authors = [{ name = "University of Oslo", email = "climate@dhis2.org" }] +readme = "README.md" +keywords = ["dhis2", "climate", "zarr", "stac", "geospatial"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Programming Language :: Python :: 3", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering :: GIS", +] dependencies = [ "fastapi>=0.100.0", "jinja2>=3.1", @@ -15,7 +28,6 @@ dependencies = [ "python-dotenv>=1.0.1", "pygeoapi>=0.22.0", "pystac>=1.10,<2", - "dhis2eo==1.2.1", "geojson-pydantic>=2.1.0", "httpx>=0.28.1", "earthkit-transforms==0.5.*", @@ -26,6 +38,10 @@ dependencies = [ "topozarr==0.0.*", ] +[project.urls] +Repository = "https://github.com/dhis2/climate-api" +Documentation = "https://github.com/dhis2/climate-api/tree/main/docs" + [project.scripts] climate-api = "climate_api.cli:main" @@ -44,7 +60,7 @@ convention = "google" [tool.ruff.lint.per-file-ignores] "tests/**/*.py" = ["D"] "**/__init__.py" = ["D104"] -"src/**/*.py" = ["D102", "D105", "D107"] +"climate_api/**/*.py" = ["D102", "D105", "D107"] [tool.ruff.format] quote-style = "double" @@ -63,18 +79,18 @@ check_untyped_defs = true no_implicit_optional = true warn_unused_ignores = true strict_equality = true -mypy_path = ["src"] +mypy_path = ["."] [[tool.mypy.overrides]] module = "tests.*" disallow_untyped_defs = false [[tool.mypy.overrides]] -module = ["dhis2eo.*", "pygeoapi.*", "rasterio.*", "pygeofilter.*", "requests.*", "geopandas.*", "earthkit.*", "metpy.*", "matplotlib.*", "yaml", "xproj", "topozarr.*", "geozarr_toolkit", "xstac"] +module = ["pygeoapi.*", "rasterio.*", "pygeofilter.*", "requests.*", "geopandas.*", "earthkit.*", "metpy.*", "matplotlib.*", "yaml", "xproj", "topozarr.*", "geozarr_toolkit", "xstac"] ignore_missing_imports = true [tool.pyright] -include = ["src", "tests"] +include = ["climate_api", "tests"] exclude = ["**/.venv"] pythonVersion = "3.13" typeCheckingMode = "strict" diff --git a/uv.lock b/uv.lock index 315fc8ee..d0e306cb 100644 --- a/uv.lock +++ b/uv.lock @@ -170,40 +170,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, ] -[[package]] -name = "cartopy" -version = "0.25.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "matplotlib" }, - { name = "numpy" }, - { name = "packaging" }, - { name = "pyproj" }, - { name = "pyshp" }, - { name = "shapely" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3c/3f/ec3dee34237b696a486d566a6d3ae6550ae821836e0412bafdcbbec2cfd2/cartopy-0.25.0.tar.gz", hash = "sha256:55f1a390e5f3f075b221c7d91fb10258ad978db786c7930eba06eb45d28753fe", size = 10767728, upload-time = "2025-08-01T12:44:16.573Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/b9/0773ff8f1c755b8a362029e6910db87064d27ca021b060c48ce511ec98b7/cartopy-0.25.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a6fcd2df8039293096f957fc9c76e969b1a9715d12ab8cee1a6bdae0c6773b8b", size = 11007728, upload-time = "2025-08-01T12:44:06.64Z" }, - { url = "https://files.pythonhosted.org/packages/34/a6/75738630b7f64bca7afc6bc5de08ddf0c61f13563f2a1abf642373d1095e/cartopy-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e4def451617e6957169447fe6ecdad0f63ef2d2007e7d451dd7b9656ada57382", size = 10996613, upload-time = "2025-08-01T12:44:08.822Z" }, - { url = "https://files.pythonhosted.org/packages/19/0d/669d4bbeb36b87ba504409d85c68ec297e6f434ea6525424f8aa5f14abac/cartopy-0.25.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c388824cb13e4fa9c2901dc4fbb2dbe9547acd2f4a6a3440983d4e6c6973ae3", size = 11829044, upload-time = "2025-08-01T12:44:11.402Z" }, - { url = "https://files.pythonhosted.org/packages/01/ff/b46e2120abd99b2ff3d376dc91ed58ae8f0a052d57c242c9b140497573dd/cartopy-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:60bad14c072d16e3c96967638cd66eb5a62cf24bc70087bcbfc6b30a3872ed26", size = 10987060, upload-time = "2025-08-01T12:44:14.222Z" }, -] - -[[package]] -name = "cdsapi" -version = "0.7.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ecmwf-datastores-client" }, - { name = "requests" }, - { name = "tqdm" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/55/f3/6cb5b4bf077c441978c5d5be3a568d37e1f07f3e7177a17fa66aec2594b6/cdsapi-0.7.7.tar.gz", hash = "sha256:bc0cf807c1b78aceba6a11c3a5180f885f47f71a4e58205e324cfedcee16f10b", size = 13322, upload-time = "2025-09-30T19:11:22.404Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/f4/4a65460d5cb6784128019fd707a87993f378db25e796eba01400a0903f62/cdsapi-0.7.7-py2.py3-none-any.whl", hash = "sha256:384c1658572d6dc53f4111f6dd46fcdfe6fea54a688af9756d71f6fe9118b66d", size = 12293, upload-time = "2025-09-30T19:11:21.184Z" }, -] - [[package]] name = "certifi" version = "2026.1.4" @@ -402,7 +368,6 @@ name = "climate-api" version = "0.1.0a1" source = { editable = "." } dependencies = [ - { name = "dhis2eo" }, { name = "earthkit-transforms" }, { name = "fastapi" }, { name = "geojson-pydantic" }, @@ -433,7 +398,6 @@ dev = [ [package.metadata] requires-dist = [ - { name = "dhis2eo", specifier = "==1.2.1" }, { name = "earthkit-transforms", specifier = "==0.5.*" }, { name = "fastapi", specifier = ">=0.100.0" }, { name = "geojson-pydantic", specifier = ">=2.1.0" }, @@ -594,27 +558,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178, upload-time = "2020-04-20T14:23:36.581Z" }, ] -[[package]] -name = "dhis2eo" -version = "1.2.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohttp" }, - { name = "earthkit-data", extra = ["cds", "geopandas", "geotiff", "projection"] }, - { name = "ecmwf-datastores-client" }, - { name = "geopandas" }, - { name = "numpy" }, - { name = "pandas" }, - { name = "requests" }, - { name = "rioxarray" }, - { name = "xarray" }, - { name = "zarr" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e5/3d/0a2945f5459bbda30e2d014a2c02417415374953e119f7a19d58c2bdf004/dhis2eo-1.2.1.tar.gz", hash = "sha256:dfc8687f033ae36758bdbc9f78ac648c50e1badf483356d35ebbee6d00f800e3", size = 22424, upload-time = "2026-05-07T11:52:09.867Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/f3/c07d21f796b809ae72858d537c68fe6be7f9f97d363ba0f76adb604b8795/dhis2eo-1.2.1-py3-none-any.whl", hash = "sha256:25fc25a8225ef7b9384a5eba6df491857562b317312cb931b8af924878fa0c52", size = 29273, upload-time = "2026-05-07T11:52:08.23Z" }, -] - [[package]] name = "donfig" version = "0.8.1.post1" @@ -657,22 +600,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/97/098f7faf1267031c54662d52791e219f95528806a744cae37014fc21be07/earthkit_data-0.16.8-py3-none-any.whl", hash = "sha256:afa6a5cc6119756be93951a75014d96ce62eb20a5acba05553a3ddca723e1a35", size = 378372, upload-time = "2026-02-18T13:34:18.988Z" }, ] -[package.optional-dependencies] -cds = [ - { name = "cdsapi" }, -] -geopandas = [ - { name = "geopandas" }, -] -geotiff = [ - { name = "pyproj" }, - { name = "rasterio" }, - { name = "rioxarray" }, -] -projection = [ - { name = "cartopy" }, -] - [[package]] name = "earthkit-meteo" version = "0.5.1" @@ -731,21 +658,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/a3/f58ff573ba0f678ff8116686e868afe436627b19b457a2aba62cd463c9ad/eccodes-2.47.0-py3-none-any.whl", hash = "sha256:13d0b28bd58e94e2c303f42415ca0dcc56ab3febf0f52b1fb0f1d4aa5e7db8e1", size = 91567, upload-time = "2026-04-22T11:30:06.789Z" }, ] -[[package]] -name = "ecmwf-datastores-client" -version = "0.4.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "multiurl" }, - { name = "requests" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/51/60/f86eb3e57baf2b1780a7046148c234e9e57b0aeb550d30f39e50991da253/ecmwf_datastores_client-0.4.2.tar.gz", hash = "sha256:7cee1f5e5dab34edcc794cd62bee02c603fafb6f4cc2121c5f012806e0f7934d", size = 48205, upload-time = "2026-01-21T15:27:31.665Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/40/2ccf4c87a5f9c8198fe71600d5f307f5dada201c091af8774a9c1e360865/ecmwf_datastores_client-0.4.2-py3-none-any.whl", hash = "sha256:d22a675b35263286de09969502ec897da9ceb9e4c8ec4d709f7ebb3b90d3ae98", size = 29092, upload-time = "2026-01-21T15:27:30.452Z" }, -] - [[package]] name = "entrypoints" version = "0.4" @@ -2248,15 +2160,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0c/82/a2c93e32800940d9573fb28c346772a14778b84ba7524e691b324620ab89/pyright-1.1.408-py3-none-any.whl", hash = "sha256:090b32865f4fdb1e0e6cd82bf5618480d48eecd2eb2e70f960982a3d9a4c17c1", size = 6399144, upload-time = "2026-01-08T08:07:37.082Z" }, ] -[[package]] -name = "pyshp" -version = "3.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/20/8b07bae73aaa0c3f5a2683ba6e23b46e977e2d33a88126d56bbcc2d135cd/pyshp-3.0.3.tar.gz", hash = "sha256:bf4678b13dd53578ed87669676a2fffeccbcded1ec8ff9cafb36d1b660f4b305", size = 2192568, upload-time = "2025-11-28T17:47:31.616Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/82/06/cad54e8ce758bd836ee5411691cbd49efeb9cc611b374670fce299519334/pyshp-3.0.3-py3-none-any.whl", hash = "sha256:28c8fac8c0c25bb0fecbbfd10ead7f319c2ff2f3b0b44a94f22bd2c93510ad42", size = 58465, upload-time = "2025-11-28T17:47:30.328Z" }, -] - [[package]] name = "pystac" version = "1.14.3" @@ -2492,22 +2395,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a", size = 64947, upload-time = "2026-03-30T16:09:13.83Z" }, ] -[[package]] -name = "rioxarray" -version = "0.19.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, - { name = "packaging" }, - { name = "pyproj" }, - { name = "rasterio" }, - { name = "xarray" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3d/8e/fe4e87460f8c62d8d5c683e09f19fbde5d9cfcfd0342d02df1f452999b5d/rioxarray-0.19.0.tar.gz", hash = "sha256:7819a0036fd874c8c8e280447cbbe43d8dc72fc4a14ac7852a665b1bdb7d4b04", size = 54600, upload-time = "2025-04-21T17:46:54.183Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/2f/63d2cacc0e525f8e3398bcf32bd3620385f22cd1600834ec49d7f3597a7b/rioxarray-0.19.0-py3-none-any.whl", hash = "sha256:494ee4fff1781072d55ee5276f5d07b63d93b05093cb33b926a12186ba5bb8ef", size = 62151, upload-time = "2025-04-21T17:46:52.801Z" }, -] - [[package]] name = "rpds-py" version = "0.30.0"