vecorel-cli 0.2.19__tar.gz → 0.2.20__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/PKG-INFO +1 -1
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/pyproject.toml +1 -1
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_convert.py +50 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/conversion/base.py +22 -5
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/conversion/duckdb.py +1 -1
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli.egg-info/PKG-INFO +1 -1
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/LICENSE +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/README.md +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/setup.cfg +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_convert_duckdb.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_converters.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_create_geojson.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_create_geoparquet.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_create_stac.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_describe.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_download.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_encoding_auto.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_encoding_geojson.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_encoding_geoparquet.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_hilbert.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_improve.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_jsonschema.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_merge.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_ops.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_rename_extension.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_validate.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/tests/test_validate_schema.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/basecommand.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/cli/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/cli/logger.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/cli/options.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/cli/path_url.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/cli/setup.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/cli/util.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/const.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/conversion/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/conversion/admin.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/conversion/flatdict.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/convert.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/converters.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/create_geojson.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/create_geoparquet.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/create_jsonschema.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/create_stac.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/datasets/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/datasets/template.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/describe.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/encoding/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/encoding/auto.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/encoding/base.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/encoding/geojson.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/encoding/geoparquet.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/improve.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/jsonschema/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/jsonschema/template.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/merge.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/parquet/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/parquet/geopandas.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/parquet/types.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/registry.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/rename_extension.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/validate.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/validate_schema.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/validation/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/validation/base.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/validation/data.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/validation/geojson.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/validation/geoparquet.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/__init__.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/collection.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/extensions.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/hilbert.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/ops.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/schemas.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/typing.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/util.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli/vecorel/version.py +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli.egg-info/SOURCES.txt +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli.egg-info/dependency_links.txt +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli.egg-info/entry_points.txt +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli.egg-info/requires.txt +0 -0
- {vecorel_cli-0.2.19 → vecorel_cli-0.2.20}/vecorel_cli.egg-info/top_level.txt +0 -0
|
@@ -199,3 +199,53 @@ def test_converter_can_keep_the_constants_in_columns(tmp_folder, monkeypatch, ch
|
|
|
199
199
|
for key in ("admin:country_code", "admin:subdivision_code", "determination_datetime"):
|
|
200
200
|
assert key in schema.names, f"{key} should have stayed a column"
|
|
201
201
|
assert key not in collection, f"{key} should not be in the collection metadata"
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_default_variant_is_chosen_before_get_urls():
|
|
205
|
+
"""A converter that overrides get_urls() must see the default variant, so the
|
|
206
|
+
default lives in convert() and not in the base get_urls() it replaces."""
|
|
207
|
+
|
|
208
|
+
class Converter(BaseConverter):
|
|
209
|
+
id = "variants"
|
|
210
|
+
# oldest first: the latest year is still the default
|
|
211
|
+
variants = {
|
|
212
|
+
"2024": "https://example.com/2024.gpkg",
|
|
213
|
+
"2025": "https://example.com/2025.gpkg",
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
def get_urls(self):
|
|
217
|
+
# like the converters that look their files up by year
|
|
218
|
+
return {f"https://example.com/{self.variant}/": f"{self.variant}.gpkg"}
|
|
219
|
+
|
|
220
|
+
converter = Converter()
|
|
221
|
+
converter.select_variant(None)
|
|
222
|
+
assert converter.variant == "2025"
|
|
223
|
+
assert converter.get_urls() == {"https://example.com/2025/": "2025.gpkg"}
|
|
224
|
+
|
|
225
|
+
converter.select_variant("2024")
|
|
226
|
+
assert converter.variant == "2024"
|
|
227
|
+
assert converter.get_urls() == {"https://example.com/2024/": "2024.gpkg"}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_default_variant_is_the_first_declared_unless_the_variants_are_years():
|
|
231
|
+
class Converter(BaseConverter):
|
|
232
|
+
id = "variants"
|
|
233
|
+
variants = {"full": "https://example.com/full.gpkg", "2025": "https://example.com/2025"}
|
|
234
|
+
|
|
235
|
+
converter = Converter()
|
|
236
|
+
converter.select_variant(None)
|
|
237
|
+
assert converter.variant == "full"
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def test_get_urls_rejects_an_unknown_variant():
|
|
241
|
+
class Converter(BaseConverter):
|
|
242
|
+
id = "variants"
|
|
243
|
+
variants = {"2025": "https://example.com/2025.gpkg"}
|
|
244
|
+
|
|
245
|
+
converter = Converter()
|
|
246
|
+
converter.select_variant("2025")
|
|
247
|
+
assert converter.get_urls() == "https://example.com/2025.gpkg"
|
|
248
|
+
|
|
249
|
+
converter.select_variant("1999")
|
|
250
|
+
with pytest.raises(ValueError, match="Unknown variant '1999'"):
|
|
251
|
+
converter.get_urls()
|
|
@@ -4,6 +4,7 @@ import hashlib
|
|
|
4
4
|
import inspect
|
|
5
5
|
import json
|
|
6
6
|
import os
|
|
7
|
+
import re
|
|
7
8
|
import sys
|
|
8
9
|
import tarfile
|
|
9
10
|
import zipfile
|
|
@@ -92,6 +93,24 @@ class BaseConverter(LoggerMixin):
|
|
|
92
93
|
"variants = {} when the inherited ones do not apply."
|
|
93
94
|
)
|
|
94
95
|
|
|
96
|
+
def select_variant(self, variant: Optional[str]) -> None:
|
|
97
|
+
"""Store the requested variant; without one, the default variant is used.
|
|
98
|
+
Done at the start of convert() rather than in get_urls(), so a converter that
|
|
99
|
+
overrides get_urls() does not have to repeat the default, and so the default is
|
|
100
|
+
also set when the user supplies the input files."""
|
|
101
|
+
self.variant = variant
|
|
102
|
+
if self.variants and self.variant is None:
|
|
103
|
+
self.variant = self.default_variant()
|
|
104
|
+
opts = ", ".join(self.variants)
|
|
105
|
+
self.warning(f"No variant given, choosing {self.variant} from {opts}")
|
|
106
|
+
|
|
107
|
+
def default_variant(self) -> str:
|
|
108
|
+
"""The latest year when the variants are years, otherwise the first declared."""
|
|
109
|
+
keys = list(self.variants)
|
|
110
|
+
if all(re.fullmatch(r"\d{4}", key) for key in keys):
|
|
111
|
+
return max(keys)
|
|
112
|
+
return keys[0]
|
|
113
|
+
|
|
95
114
|
def _check_id_mapping(self):
|
|
96
115
|
"""Warn before converting when nothing is mapped to the required `id` property.
|
|
97
116
|
Unmapped columns are dropped, which also removes the column filled by
|
|
@@ -344,13 +363,11 @@ class BaseConverter(LoggerMixin):
|
|
|
344
363
|
def get_urls(self):
|
|
345
364
|
urls = self.sources
|
|
346
365
|
if not urls and self.variants:
|
|
347
|
-
|
|
348
|
-
if self.variant is None:
|
|
349
|
-
self.variant = next(iter(self.variants))
|
|
350
|
-
self.warning(f"Choosing first available variant {self.variant} from {opts}")
|
|
366
|
+
# the default variant is chosen in convert(), see select_variant()
|
|
351
367
|
if self.variant in self.variants:
|
|
352
368
|
urls = self.variants[self.variant]
|
|
353
369
|
else:
|
|
370
|
+
opts = ", ".join(self.variants)
|
|
354
371
|
raise ValueError(f"Unknown variant '{self.variant}', choose from {opts}")
|
|
355
372
|
return urls
|
|
356
373
|
|
|
@@ -483,7 +500,7 @@ class BaseConverter(LoggerMixin):
|
|
|
483
500
|
original_geometries=False,
|
|
484
501
|
**kwargs,
|
|
485
502
|
) -> str:
|
|
486
|
-
self.variant
|
|
503
|
+
self.select_variant(variant)
|
|
487
504
|
cid = self.id.strip()
|
|
488
505
|
if self.bbox is not None and len(self.bbox) != 4:
|
|
489
506
|
raise ValueError("If provided, the bounding box must consist of 4 numbers")
|
|
@@ -74,7 +74,7 @@ class DuckDBBaseConverter(BaseConverter):
|
|
|
74
74
|
original_geometries=False,
|
|
75
75
|
**kwargs,
|
|
76
76
|
) -> str:
|
|
77
|
-
self.variant
|
|
77
|
+
self.select_variant(variant)
|
|
78
78
|
cid = self.id.strip()
|
|
79
79
|
if self.bbox is not None and len(self.bbox) != 4:
|
|
80
80
|
raise ValueError("If provided, the bounding box must consist of 4 numbers")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|