vecorel-cli 0.2.16__tar.gz → 0.2.17__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.
Files changed (79) hide show
  1. {vecorel_cli-0.2.16/vecorel_cli.egg-info → vecorel_cli-0.2.17}/PKG-INFO +1 -1
  2. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/pyproject.toml +1 -1
  3. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_convert.py +21 -0
  4. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_encoding_geojson.py +23 -0
  5. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/conversion/base.py +4 -0
  6. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/encoding/geojson.py +8 -3
  7. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17/vecorel_cli.egg-info}/PKG-INFO +1 -1
  8. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/LICENSE +0 -0
  9. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/README.md +0 -0
  10. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/setup.cfg +0 -0
  11. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_converters.py +0 -0
  12. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_create_geojson.py +0 -0
  13. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_create_geoparquet.py +0 -0
  14. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_create_stac.py +0 -0
  15. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_describe.py +0 -0
  16. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_encoding_auto.py +0 -0
  17. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_encoding_geoparquet.py +0 -0
  18. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_improve.py +0 -0
  19. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_jsonschema.py +0 -0
  20. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_merge.py +0 -0
  21. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_ops.py +0 -0
  22. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_rename_extension.py +0 -0
  23. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_validate.py +0 -0
  24. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/tests/test_validate_schema.py +0 -0
  25. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/__init__.py +0 -0
  26. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/basecommand.py +0 -0
  27. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/cli/__init__.py +0 -0
  28. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/cli/logger.py +0 -0
  29. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/cli/options.py +0 -0
  30. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/cli/path_url.py +0 -0
  31. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/cli/setup.py +0 -0
  32. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/cli/util.py +0 -0
  33. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/const.py +0 -0
  34. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/conversion/__init__.py +0 -0
  35. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/conversion/admin.py +0 -0
  36. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/conversion/flatdict.py +0 -0
  37. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/convert.py +0 -0
  38. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/converters.py +0 -0
  39. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/create_geojson.py +0 -0
  40. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/create_geoparquet.py +0 -0
  41. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/create_jsonschema.py +0 -0
  42. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/create_stac.py +0 -0
  43. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/datasets/__init__.py +0 -0
  44. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/datasets/template.py +0 -0
  45. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/describe.py +0 -0
  46. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/encoding/__init__.py +0 -0
  47. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/encoding/auto.py +0 -0
  48. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/encoding/base.py +0 -0
  49. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/encoding/geoparquet.py +0 -0
  50. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/improve.py +0 -0
  51. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/jsonschema/__init__.py +0 -0
  52. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/jsonschema/template.py +0 -0
  53. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/merge.py +0 -0
  54. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/parquet/__init__.py +0 -0
  55. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/parquet/geopandas.py +0 -0
  56. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/parquet/types.py +0 -0
  57. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/registry.py +0 -0
  58. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/rename_extension.py +0 -0
  59. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/validate.py +0 -0
  60. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/validate_schema.py +0 -0
  61. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/validation/__init__.py +0 -0
  62. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/validation/base.py +0 -0
  63. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/validation/data.py +0 -0
  64. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/validation/geojson.py +0 -0
  65. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/validation/geoparquet.py +0 -0
  66. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/__init__.py +0 -0
  67. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/collection.py +0 -0
  68. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/extensions.py +0 -0
  69. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/hilbert.py +0 -0
  70. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/ops.py +0 -0
  71. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/schemas.py +0 -0
  72. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/typing.py +0 -0
  73. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/util.py +0 -0
  74. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli/vecorel/version.py +0 -0
  75. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli.egg-info/SOURCES.txt +0 -0
  76. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli.egg-info/dependency_links.txt +0 -0
  77. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli.egg-info/entry_points.txt +0 -0
  78. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli.egg-info/requires.txt +0 -0
  79. {vecorel_cli-0.2.16 → vecorel_cli-0.2.17}/vecorel_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vecorel-cli
3
- Version: 0.2.16
3
+ Version: 0.2.17
4
4
  Summary: CLI tools such as validation and file format conversion for vecorel.
5
5
  Author: Matthias Mohr
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vecorel-cli"
7
- version = "0.2.16"
7
+ version = "0.2.17"
8
8
  description = "CLI tools such as validation and file format conversion for vecorel."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import sys
2
3
  from pathlib import Path
3
4
 
@@ -146,6 +147,26 @@ def test_template_from_package_folder():
146
147
  assert isinstance(converter, ConvertData), "Should succeed and not throw an exception"
147
148
 
148
149
 
150
+ @pytest.mark.parametrize("bom", [False, True], ids=["without-bom", "with-bom"])
151
+ def test_read_geojson_decodes_utf8(tmp_folder, cp1252_locale, bom):
152
+ file_path = tmp_folder / "umlaut.json"
153
+ feature = {
154
+ "type": "Feature",
155
+ "id": "1",
156
+ "properties": {"name": "Grünland"},
157
+ "geometry": {"type": "Point", "coordinates": [0, 0]},
158
+ }
159
+ file_path.write_text(
160
+ # ensure_ascii=False so the file really holds multi-byte UTF-8, not an escape sequence
161
+ json.dumps({"type": "FeatureCollection", "features": [feature]}, ensure_ascii=False),
162
+ encoding="utf-8-sig" if bom else "utf-8",
163
+ )
164
+
165
+ gdf = BaseConverter().read_geojson(str(file_path))
166
+
167
+ assert gdf["name"].iloc[0] == "Grünland"
168
+
169
+
149
170
  def test_data_access_exception(capsys, tmp_folder):
150
171
  # todo: use fixture
151
172
  logger.remove()
@@ -1,3 +1,4 @@
1
+ import json
1
2
  from pathlib import Path
2
3
 
3
4
  import pytest
@@ -55,3 +56,25 @@ def test_get_collection_returns_existing(tmp_folder):
55
56
 
56
57
  result = geojson.get_collection()
57
58
  assert result == expected
59
+
60
+
61
+ @pytest.mark.parametrize("bom", [False, True], ids=["without-bom", "with-bom"])
62
+ def test_read_geojson_decodes_utf8(tmp_folder, cp1252_locale, bom):
63
+ feature = {
64
+ "type": "Feature",
65
+ "id": "1",
66
+ "properties": {"name": "Grünland"},
67
+ "geometry": {"type": "Point", "coordinates": [0, 0]},
68
+ }
69
+ file_path = tmp_folder / "umlaut.json"
70
+ file_path.write_text(
71
+ # ensure_ascii=False so the file really holds multi-byte UTF-8, not an escape sequence
72
+ json.dumps({"type": "FeatureCollection", "features": [feature]}, ensure_ascii=False),
73
+ encoding="utf-8-sig" if bom else "utf-8",
74
+ )
75
+
76
+ geojson = GeoJSON(file_path)
77
+
78
+ assert geojson.read_geojson()["features"][0]["properties"]["name"] == "Grünland"
79
+ # read(num=...) takes the streaming branch, which opens the file separately
80
+ assert geojson.read(num=1)["name"].iloc[0] == "Grünland"
@@ -24,6 +24,7 @@ from geopandas import GeoDataFrame
24
24
 
25
25
  from ..cli.logger import LoggerMixin
26
26
  from ..cli.util import display_pandas_unrestricted
27
+ from ..encoding.geojson import READ_ENCODING
27
28
  from ..encoding.geoparquet import GeoParquet
28
29
  from ..vecorel.collection import Collection
29
30
  from ..vecorel.hilbert import hilbert_sort_geodataframe
@@ -218,6 +219,9 @@ class BaseConverter(LoggerMixin):
218
219
  yield GeoDataFrame(data), path, uri, layer
219
220
 
220
221
  def read_geojson(self, path, **kwargs):
222
+ # open_options is shared with gpd.read_parquet() and gpd.read_file(), so a converter
223
+ # cannot set a default encoding there without breaking the other two readers.
224
+ kwargs.setdefault("encoding", READ_ENCODING)
221
225
  with open(path, **kwargs) as f:
222
226
  obj = json.load(f)
223
227
 
@@ -17,6 +17,11 @@ from ..vecorel.util import load_file, to_iso8601
17
17
  from ..vecorel.version import vecorel_version
18
18
  from .base import BaseEncoding
19
19
 
20
+ # GeoJSON is UTF-8 (RFC 8259, section 8.1). Reading tolerates a byte order mark, which some
21
+ # producers emit; writing must not add one, so the two differ.
22
+ READ_ENCODING = "utf-8-sig"
23
+ WRITE_ENCODING = "utf-8"
24
+
20
25
 
21
26
  class GeoJSON(BaseEncoding):
22
27
  feature_properties = {"type", "id", "geometry", "bbox", "properties"}
@@ -152,7 +157,7 @@ class GeoJSON(BaseEncoding):
152
157
  enforce_featurecollection: bool = False,
153
158
  ) -> Union[FeatureCollection, Feature]:
154
159
  # num only applies to FeatureCollections
155
- with open(self.uri, "r") as f:
160
+ with open(self.uri, "r", encoding=READ_ENCODING) as f:
156
161
  obj = json.load(f)
157
162
 
158
163
  if not isinstance(obj, dict):
@@ -233,7 +238,7 @@ class GeoJSON(BaseEncoding):
233
238
  schema_map: SchemaMapping = {},
234
239
  properties: Optional[list[str]] = None,
235
240
  ) -> GeoDataFrame:
236
- with open(self.uri, "r") as f:
241
+ with open(self.uri, "r", encoding=READ_ENCODING) as f:
237
242
  stream = json_stream.load(f)
238
243
  data = {
239
244
  "id": [],
@@ -291,7 +296,7 @@ class GeoJSON(BaseEncoding):
291
296
  return gdf
292
297
 
293
298
  def _write_json(self, obj, path, indent=None) -> bool:
294
- with open(path, "w") as f:
299
+ with open(path, "w", encoding=WRITE_ENCODING) as f:
295
300
  json.dump(obj, f, allow_nan=False, indent=indent, cls=VecorelJSONEncoder)
296
301
  return True
297
302
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vecorel-cli
3
- Version: 0.2.16
3
+ Version: 0.2.17
4
4
  Summary: CLI tools such as validation and file format conversion for vecorel.
5
5
  Author: Matthias Mohr
6
6
  License-Expression: Apache-2.0
File without changes
File without changes
File without changes