diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b8d5408..8f4c05d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Collection-only properties are kept when merging collections - Default GeoParquet compression is now zstd (level 15), configurable via `--compression_level` - DE-SH: make the 2023, 2025 and 2026 editions convert — glob the GeoPackage inside the archive (2023 was written with user_version = 0, so the archive alone matches no driver), parse fachguelti as DD.MM.YYYY, and map the 2023 and upper-case 2025/2026 column spellings that silently dropped determination:datetime and metrics:area (their area is text with a decimal comma) +- Add DuckDB BaseConverter for efficiently transforming large datasets +- Update vecorel-cli to v0.2.18: + - The DuckDB converter base and the GeoParquet post-processing live there now + - Converters record the collection id in the collection metadata instead of a constant `collection` column + - Converters drop rows that can never validate (missing required values, empty or missing geometries), bounded by `max_dropped_share` + - Converters fail when both `sources` and `variants` are declared (fixed in the HR converter), and warn when no column is mapped to `id` or the id column is not unique + - Converters load all schemas upfront with retries ## [v0.21.0] - 2026-02-16 @@ -49,6 +56,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fix the column additions of the determination fields in the AI4SF converter - Add HCAT to datasets where possible - Updated years & variants for at_crop, be_vlg, es_an, es_cl, es_pv, ie, pt, se +- Add DuckDB BaseConverter for efficiently transforming large datasets - Extend create_stac, include include fiboa data - Publish command; skip hidden files, generate better texts - Fix to vecorel: converter.license and provider should be string diff --git a/fiboa_cli/conversion/duckdb.py b/fiboa_cli/conversion/duckdb.py new file mode 100644 index 00000000..f23c8da2 --- /dev/null +++ b/fiboa_cli/conversion/duckdb.py @@ -0,0 +1,10 @@ +from vecorel_cli.conversion.duckdb import DuckDBBaseConverter + +from .fiboa_converter import FiboaBaseConverter + + +# This converter is experimental, use with caution. +# Results may not be fully fiboa compliant yet. +# Use this primarily for datasets that are too large to be processed by the default converter +class FiboaDuckDBBaseConverter(DuckDBBaseConverter, FiboaBaseConverter): + pass diff --git a/fiboa_cli/datasets/commons/euro_land.py b/fiboa_cli/datasets/commons/euro_land.py index f33bee51..5294c22e 100644 --- a/fiboa_cli/datasets/commons/euro_land.py +++ b/fiboa_cli/datasets/commons/euro_land.py @@ -47,3 +47,11 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) provider = "Europe-LAND HE Project " self.provider = (f"{self.provider}, {provider}") if self.provider else provider + + def migrate(self, gdf): + # Some Europe-LAND files (e.g. LT 2024) ship an empty crop_code column next to + # a populated crop_name; the name is then the best available crop code. + if "crop_code" in gdf.columns and gdf["crop_code"].isna().all(): + self.warning("crop_code is empty, using crop_name as crop:code") + gdf["crop_code"] = gdf["crop_name"] + return super().migrate(gdf) diff --git a/fiboa_cli/datasets/hr.py b/fiboa_cli/datasets/hr.py index 834deb5b..d0c923dc 100644 --- a/fiboa_cli/datasets/hr.py +++ b/fiboa_cli/datasets/hr.py @@ -7,7 +7,6 @@ class Converter(AdminConverterMixin, AddHCATMixin, FiboaBaseConverter): - sources = "https://www.apprrr.hr/wp-content/uploads/nipp/land_parcels.gpkg" variants = { "2024": f"{base}/land_parcels.gpkg", **{str(y): f"{base}/arkod_31_12_{y}.gpkg" for y in range(2023, 2010, -1)}, diff --git a/fiboa_cli/datasets/jp.py b/fiboa_cli/datasets/jp.py index 57c31a24..1799c7f4 100644 --- a/fiboa_cli/datasets/jp.py +++ b/fiboa_cli/datasets/jp.py @@ -1,10 +1,9 @@ -import pandas as pd +from fiboa_cli.conversion.duckdb import FiboaDuckDBBaseConverter -from ..conversion.fiboa_converter import FiboaBaseConverter - -class JPConverter(FiboaBaseConverter): +class JPConverter(FiboaDuckDBBaseConverter): variants = { + "test": "./tests/data-files/convert/jp/jp_field_polygons_2024.parquet", "2024": "https://data.source.coop/pacificspatial/field-polygon-jp/parquet/jp_field_polygons_2024.parquet", "2023": "https://data.source.coop/pacificspatial/field-polygon-jp/parquet/jp_field_polygons_2023.parquet", "2022": "https://data.source.coop/pacificspatial/field-polygon-jp/parquet/jp_field_polygons_2022.parquet", @@ -30,23 +29,11 @@ class JPConverter(FiboaBaseConverter): "polygon_uuid": "id", "land_type_en": "land_type_en", "local_government_cd": "admin_local_code", - "issue_year": "determination:datetime", - } - column_migrations = { - "issue_year": lambda col: pd.to_datetime(col, format="%Y"), } - + column_additions = {"determination:datetime": "2024-01-01T00:00:00Z"} missing_schemas = { "properties": { "land_type_en": {"type": "string"}, "admin_local_code": {"type": "string"}, } } - - def convert(self, *args, **kwargs): - # Open only these columns to limit memory usage - super().convert( - *args, - columns=["GEOM", "polygon_uuid", "land_type_en", "local_government_cd", "issue_year"], - **kwargs, - ) diff --git a/fiboa_cli/datasets/lt.py b/fiboa_cli/datasets/lt.py index 42a00b3a..e174aa85 100644 --- a/fiboa_cli/datasets/lt.py +++ b/fiboa_cli/datasets/lt.py @@ -1,5 +1,7 @@ from fiboa_cli.datasets.commons.euro_land import EuroLandBaseConverter +BASE = "https://zenodo.org/records/18670815/files" + class LTConverter(EuroLandBaseConverter): id = "lt" @@ -10,4 +12,12 @@ class LTConverter(EuroLandBaseConverter): provider = "Nacionalinė mokėjimo agentūra prie Žemės ūkio ministerijos " attribution = "Nacionalinė mokėjimo agentūra prie Žemės ūkio ministerijos" ec_mapping_csv = "lt_2021.csv" - sources = {"https://zenodo.org/records/14384070/files/LT_2024.zip": ["GSA-LT-2024.geoparquet"]} + # Europe-LAND v1.3 (record 18670815, February 2026) bundles both editions in + # one archive; v1.1 (record 14384070), which this converter used to read, + # carried 2024 alone. + variants = { + str(year): {f"{BASE}/LT_years_2024-2025.zip": [f"GSA-LT-{year}.geoparquet"]} + for year in (2025, 2024) + } + # The inventory carries no per-feature date, so the edition is the year. + use_variant_as_determination = True diff --git a/pixi.lock b/pixi.lock index 118896d5..fee018c9 100644 --- a/pixi.lock +++ b/pixi.lock @@ -141,6 +141,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/35/b1fae4c5245697837f6f63e407fa81e7ccc7948f6ef2b124cd38736f4d1d/duckdb-1.4.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/90/72/0b6035302e9c33f004240a50cb6e2e1fc7bb1f2b415b02d939c551bdd06b/inflate64-1.0.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl @@ -173,7 +174,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-64: @@ -302,6 +303,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/ab/e04a8f97865251b544aee9501088d4f0cb8e8b37339bd465c0d33857d411/duckdb-1.4.2-cp314-cp314-macosx_10_15_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/80/24ba0d2ee14e07e275e9c5b058e59a8a58f8ef42dd51a78ebbfd7c857ac4/inflate64-1.0.4-cp314-cp314-macosx_10_15_x86_64.whl @@ -334,7 +336,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-arm64: @@ -464,6 +466,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/ec/b8229517c2f9fe88a38bb1a172a2da4d0ff34996d319d74554fda80b6358/duckdb-1.4.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/b8/073a79716e093db973b8823bdfb02e10fbdf65642dbe1fa3cda24832aeb2/inflate64-1.0.4-cp314-cp314-macosx_11_0_arm64.whl @@ -496,7 +499,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ win-64: @@ -624,6 +627,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/5e/6f5ebaabc12c6db62f471f86b5c9c8debd57f11aa1b2acbbcc4c68683238/duckdb-1.4.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dd/51/f2972df8cceecc9bf3afa3353d517ffc7125285198c844588e9aaf98f5d0/inflate64-1.0.4-cp314-cp314-win_amd64.whl @@ -656,7 +660,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl - pypi: ./ @@ -777,6 +781,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/35/b1fae4c5245697837f6f63e407fa81e7ccc7948f6ef2b124cd38736f4d1d/duckdb-1.4.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/90/72/0b6035302e9c33f004240a50cb6e2e1fc7bb1f2b415b02d939c551bdd06b/inflate64-1.0.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl @@ -808,7 +813,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-64: @@ -913,6 +918,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/ab/e04a8f97865251b544aee9501088d4f0cb8e8b37339bd465c0d33857d411/duckdb-1.4.2-cp314-cp314-macosx_10_15_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/80/24ba0d2ee14e07e275e9c5b058e59a8a58f8ef42dd51a78ebbfd7c857ac4/inflate64-1.0.4-cp314-cp314-macosx_10_15_x86_64.whl @@ -944,7 +950,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-arm64: @@ -1050,6 +1056,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/ec/b8229517c2f9fe88a38bb1a172a2da4d0ff34996d319d74554fda80b6358/duckdb-1.4.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/b8/073a79716e093db973b8823bdfb02e10fbdf65642dbe1fa3cda24832aeb2/inflate64-1.0.4-cp314-cp314-macosx_11_0_arm64.whl @@ -1081,7 +1088,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ win-64: @@ -1186,6 +1193,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/5e/6f5ebaabc12c6db62f471f86b5c9c8debd57f11aa1b2acbbcc4c68683238/duckdb-1.4.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dd/51/f2972df8cceecc9bf3afa3353d517ffc7125285198c844588e9aaf98f5d0/inflate64-1.0.4-cp314-cp314-win_amd64.whl @@ -1217,7 +1225,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl - pypi: ./ @@ -1300,6 +1308,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/35/b1fae4c5245697837f6f63e407fa81e7ccc7948f6ef2b124cd38736f4d1d/duckdb-1.4.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/90/72/0b6035302e9c33f004240a50cb6e2e1fc7bb1f2b415b02d939c551bdd06b/inflate64-1.0.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl @@ -1331,7 +1340,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-64: @@ -1399,6 +1408,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/ab/e04a8f97865251b544aee9501088d4f0cb8e8b37339bd465c0d33857d411/duckdb-1.4.2-cp314-cp314-macosx_10_15_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/80/24ba0d2ee14e07e275e9c5b058e59a8a58f8ef42dd51a78ebbfd7c857ac4/inflate64-1.0.4-cp314-cp314-macosx_10_15_x86_64.whl @@ -1430,7 +1440,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-arm64: @@ -1499,6 +1509,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/ec/b8229517c2f9fe88a38bb1a172a2da4d0ff34996d319d74554fda80b6358/duckdb-1.4.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/b8/073a79716e093db973b8823bdfb02e10fbdf65642dbe1fa3cda24832aeb2/inflate64-1.0.4-cp314-cp314-macosx_11_0_arm64.whl @@ -1530,7 +1541,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ win-64: @@ -1596,6 +1607,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/yarl-1.22.0-pyh7db6752_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/5e/6f5ebaabc12c6db62f471f86b5c9c8debd57f11aa1b2acbbcc4c68683238/duckdb-1.4.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dd/51/f2972df8cceecc9bf3afa3353d517ffc7125285198c844588e9aaf98f5d0/inflate64-1.0.4-cp314-cp314-win_amd64.whl @@ -1627,7 +1639,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl - pypi: ./ @@ -1736,6 +1748,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/23/35/b1fae4c5245697837f6f63e407fa81e7ccc7948f6ef2b124cd38736f4d1d/duckdb-1.4.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/90/72/0b6035302e9c33f004240a50cb6e2e1fc7bb1f2b415b02d939c551bdd06b/inflate64-1.0.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl @@ -1768,7 +1781,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-64: @@ -1862,6 +1875,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/ab/e04a8f97865251b544aee9501088d4f0cb8e8b37339bd465c0d33857d411/duckdb-1.4.2-cp314-cp314-macosx_10_15_x86_64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/80/24ba0d2ee14e07e275e9c5b058e59a8a58f8ef42dd51a78ebbfd7c857ac4/inflate64-1.0.4-cp314-cp314-macosx_10_15_x86_64.whl @@ -1894,7 +1908,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ osx-arm64: @@ -1989,6 +2003,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/ec/b8229517c2f9fe88a38bb1a172a2da4d0ff34996d319d74554fda80b6358/duckdb-1.4.2-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/b8/073a79716e093db973b8823bdfb02e10fbdf65642dbe1fa3cda24832aeb2/inflate64-1.0.4-cp314-cp314-macosx_11_0_arm64.whl @@ -2021,7 +2036,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: ./ win-64: @@ -2112,6 +2127,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda - pypi: https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/5e/6f5ebaabc12c6db62f471f86b5c9c8debd57f11aa1b2acbbcc4c68683238/duckdb-1.4.2-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dd/51/f2972df8cceecc9bf3afa3353d517ffc7125285198c844588e9aaf98f5d0/inflate64-1.0.4-cp314-cp314-win_amd64.whl @@ -2144,7 +2160,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/24/99/4772b8e00a136f3e01236de33b0efda31ee7077203ba5967fcc76da94d65/texttable-1.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl - pypi: ./ @@ -2789,6 +2805,54 @@ packages: - pkg:pypi/distlib?source=hash-mapping size: 275642 timestamp: 1752823081585 +- pypi: https://files.pythonhosted.org/packages/23/35/b1fae4c5245697837f6f63e407fa81e7ccc7948f6ef2b124cd38736f4d1d/duckdb-1.4.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + name: duckdb + version: 1.4.2 + sha256: 128c97dab574a438d7c8d020670b21c68792267d88e65a7773667b556541fa9b + requires_dist: + - ipython ; extra == 'all' + - fsspec ; extra == 'all' + - numpy ; extra == 'all' + - pandas ; extra == 'all' + - pyarrow ; extra == 'all' + - adbc-driver-manager ; extra == 'all' + requires_python: '>=3.9.0' +- pypi: https://files.pythonhosted.org/packages/25/5e/6f5ebaabc12c6db62f471f86b5c9c8debd57f11aa1b2acbbcc4c68683238/duckdb-1.4.2-cp314-cp314-win_amd64.whl + name: duckdb + version: 1.4.2 + sha256: dfcc56a83420c0dec0b83e97a6b33addac1b7554b8828894f9d203955591218c + requires_dist: + - ipython ; extra == 'all' + - fsspec ; extra == 'all' + - numpy ; extra == 'all' + - pandas ; extra == 'all' + - pyarrow ; extra == 'all' + - adbc-driver-manager ; extra == 'all' + requires_python: '>=3.9.0' +- pypi: https://files.pythonhosted.org/packages/47/ec/b8229517c2f9fe88a38bb1a172a2da4d0ff34996d319d74554fda80b6358/duckdb-1.4.2-cp314-cp314-macosx_11_0_arm64.whl + name: duckdb + version: 1.4.2 + sha256: 20c45b4ead1ea4d23a1be1cd4f1dfc635e58b55f0dd11e38781369be6c549903 + requires_dist: + - ipython ; extra == 'all' + - fsspec ; extra == 'all' + - numpy ; extra == 'all' + - pandas ; extra == 'all' + - pyarrow ; extra == 'all' + - adbc-driver-manager ; extra == 'all' + requires_python: '>=3.9.0' +- pypi: https://files.pythonhosted.org/packages/82/ab/e04a8f97865251b544aee9501088d4f0cb8e8b37339bd465c0d33857d411/duckdb-1.4.2-cp314-cp314-macosx_10_15_x86_64.whl + name: duckdb + version: 1.4.2 + sha256: 459b1855bd06a226a2838da4f14c8863fd87a62e63d414a7f7f682a7c616511a + requires_dist: + - ipython ; extra == 'all' + - fsspec ; extra == 'all' + - numpy ; extra == 'all' + - pandas ; extra == 'all' + - pyarrow ; extra == 'all' + - adbc-driver-manager ; extra == 'all' + requires_python: '>=3.9.0' - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 md5: 8e662bd460bda79b1ea39194e3c4c9ab @@ -2803,10 +2867,11 @@ packages: - pypi: ./ name: fiboa-cli version: 0.21.0 - sha256: a97f8b680673e3f70718b7081f3783d28ffe6e8040e4dd85a9cbac167a7ac574 + sha256: 544a959421501ea1dcf28cede8c6b5c41b70ce5ddeb55f0c4ed1a54fc32c2d64 requires_dist: - - vecorel-cli==0.2.17 + - vecorel-cli==0.2.15 - spdx-license-list==3.27.0 + - duckdb==1.4.2 requires_python: '>=3.11' editable: true - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.21.2-pyhd8ed1ab_0.conda @@ -7075,10 +7140,10 @@ packages: purls: [] size: 115235 timestamp: 1767320173250 -- pypi: https://files.pythonhosted.org/packages/ee/c8/f2e3096528f7f2dbf4069ab998137e001da38576b2755da2d2ee9289a5eb/vecorel_cli-0.2.17-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/da/b6/ba9cfde9eb83094a6642a42f036b90f74dcff9abdd307cbdd21dc996e562/vecorel_cli-0.2.15-py3-none-any.whl name: vecorel-cli - version: 0.2.17 - sha256: b62387569ededb111cffd7339fede015c747176b59cfdd77bd4f2259f5ce60c4 + version: 0.2.15 + sha256: b8e297b5967521b994dc7342aa72cf43cc0a0326609d8e7c4afb32d09c9f786c requires_dist: - pyyaml>=6.0,<7.0 - click>=8.1,<9.0 @@ -7088,7 +7153,7 @@ packages: - numpy>=2.0,<3.0 - pyarrow>=21.0,<24.0 - py7zr>=1.0,<2.0 - - fsspec>=2025.7.0 + - fsspec==2025.7.0 - jsonschema[format]>=4.20,<5.0 - aiohttp>=3.9,<4.0 - yarl>=1.20,<2.0 @@ -7096,10 +7161,6 @@ packages: - semantic-version>=2.10.0,<3.0 - json-stream>=2.3.0,<3.0 - loguru==0.7.3 - - s3fs>=2025.7.0 ; extra == 's3' - - gcsfs>=2025.7.0 ; extra == 'gcs' - - s3fs>=2025.7.0 ; extra == 'cloud' - - gcsfs>=2025.7.0 ; extra == 'cloud' requires_python: '>=3.11' - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.36.1-pyhd8ed1ab_0.conda sha256: fa0a21fdcd0a8e6cf64cc8cd349ed6ceb373f09854fd3c4365f0bc4586dccf9a diff --git a/pyproject.toml b/pyproject.toml index de306340..20c352ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ classifiers = [ ] requires-python = ">=3.11" dependencies = [ - "vecorel-cli==0.2.17", + "vecorel-cli==0.2.18", "spdx-license-list==3.27.0", ] @@ -64,8 +64,8 @@ ruff = "==0.12.8" build = ">=1.0.0,<2.0.0" [tool.pixi.feature.cloud.dependencies] -s3fs = ">=2025.7.0" -gcsfs = ">=2025.7.0" +s3fs = "==2025.7.0" +gcsfs = "==2025.7.0" [tool.pixi.environments] default = {solve-group = "default"} @@ -107,7 +107,7 @@ exclude = [ line-length = 100 indent-width = 4 -target-version = "py311" +target-version = "py310" [tool.ruff.lint] select = ["E4", "E7", "E9", "F", "W", "I", "NPY201"] # "C901" diff --git a/tests/data-files/convert/lt/LT_2024.zip b/tests/data-files/convert/lt/LT_years_2024-2025.zip similarity index 100% rename from tests/data-files/convert/lt/LT_2024.zip rename to tests/data-files/convert/lt/LT_years_2024-2025.zip diff --git a/tests/test_convert.py b/tests/test_convert.py index 3ac24a11..d838f81c 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -71,6 +71,8 @@ def _input_files(converter, *names): extra_convert_parameters = { "ai4sf": _input_files("ai4sf", "1_vietnam_areas.gpkg", "4_cambodia_areas.gpkg"), + # the fixture archive holds the 2024 edition only + "lt": {"variant": "2024"}, "nl": {"variant": "2023"}, "se": {"variant": "2023"}, "si": {"variant": "2023"}, diff --git a/tests/test_convert_parity.py b/tests/test_convert_parity.py new file mode 100644 index 00000000..a889f284 --- /dev/null +++ b/tests/test_convert_parity.py @@ -0,0 +1,100 @@ +import json + +import pyarrow.parquet as pq +import shapely + +from fiboa_cli.conversion.fiboa_converter import FiboaBaseConverter +from fiboa_cli.datasets.jp import JPConverter +from fiboa_cli.validate import ValidateData + +# A GeoDataFrame-based twin of the DuckDB-based jp converter, built from the +# same configuration so that the two codepaths cannot drift apart. +SHARED_ATTRIBUTES = ( + "id", + "short_name", + "title", + "description", + "provider", + "attribution", + "license", + "variants", + "columns", + "column_additions", + "missing_schemas", +) +PandasJPConverter = type( + "PandasJPConverter", + (FiboaBaseConverter,), + {key: getattr(JPConverter, key) for key in SHARED_ATTRIBUTES}, +) + + +def test_jp_codepath_parity(tmp_folder): + """The DuckDB-based jp converter and its GeoDataFrame-based twin must + produce comparable files: same schema, same rows in the same order, + same key metadata, same packaging.""" + kwargs = {"variant": "test", "compression": "zstd", "geoparquet_version": "1.1.0"} + pandas_dest = tmp_folder / "pandas.parquet" + duckdb_dest = tmp_folder / "duckdb.parquet" + PandasJPConverter().convert(pandas_dest, **kwargs) + JPConverter().convert(duckdb_dest, **kwargs) + + with pq.ParquetFile(pandas_dest) as pf: + pandas_schema = pf.schema_arrow + pandas_table = pf.read() + pandas_groups = pf.metadata.num_row_groups + pandas_compression = pf.metadata.row_group(0).column(0).compression + with pq.ParquetFile(duckdb_dest) as pf: + duckdb_schema = pf.schema_arrow + duckdb_table = pf.read() + duckdb_groups = pf.metadata.num_row_groups + duckdb_compression = pf.metadata.row_group(0).column(0).compression + + # Same columns with the same types and nullability (the column order is + # allowed to differ) + assert sorted(pandas_schema.names) == sorted(duckdb_schema.names) + for name in pandas_schema.names: + f1, f2 = pandas_schema.field(name), duckdb_schema.field(name) + assert f1.type == f2.type, f"{name}: {f1.type} != {f2.type}" + assert f1.nullable == f2.nullable, f"{name}: nullability differs" + + # Same rows in the same order: both codepaths sort against the same Hilbert + # grid and resolve ties by source order. The geometries must describe the + # same shapes, but the WKB may differ in vertex order (different GEOS builds) + assert pandas_table.num_rows == duckdb_table.num_rows + for column in pandas_schema.names: + if column in ("geometry", "bbox"): + continue + assert pandas_table[column].to_pylist() == duckdb_table[column].to_pylist(), ( + f"{column}: values differ" + ) + pandas_geoms = shapely.from_wkb(pandas_table["geometry"].to_pylist()) + duckdb_geoms = shapely.from_wkb(duckdb_table["geometry"].to_pylist()) + for g1, g2 in zip(pandas_geoms, duckdb_geoms): + assert shapely.equals(g1, g2) + + # Same collection metadata and the same key GeoParquet metadata + pandas_collection = json.loads(pandas_schema.metadata[b"collection"]) + duckdb_collection = json.loads(duckdb_schema.metadata[b"collection"]) + assert pandas_collection == duckdb_collection + + pandas_geo = json.loads(pandas_schema.metadata[b"geo"]) + duckdb_geo = json.loads(duckdb_schema.metadata[b"geo"]) + for key in ("version", "primary_column"): + assert pandas_geo[key] == duckdb_geo[key] + pandas_column = pandas_geo["columns"]["geometry"] + duckdb_column = duckdb_geo["columns"]["geometry"] + for key in ("encoding", "covering", "crs", "bbox"): + assert pandas_column.get(key) == duckdb_column.get(key), f"geo {key} differs" + assert sorted(pandas_column.get("geometry_types", [])) == sorted( + duckdb_column.get("geometry_types", []) + ) + + # Same packaging + assert pandas_compression == duckdb_compression + assert pandas_groups == duckdb_groups + + # Both validate + for dest in (pandas_dest, duckdb_dest): + validation = ValidateData().validate(dest, num=100, schema_map={}) + assert validation.errors == []