stac-valid 4.2.0__tar.gz → 4.2.2__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 (34) hide show
  1. {stac_valid-4.2.0/stac_valid.egg-info → stac_valid-4.2.2}/PKG-INFO +71 -1
  2. {stac_valid-4.2.0 → stac_valid-4.2.2}/README.md +69 -0
  3. {stac_valid-4.2.0 → stac_valid-4.2.2}/pyproject.toml +2 -1
  4. {stac_valid-4.2.0 → stac_valid-4.2.2/stac_valid.egg-info}/PKG-INFO +71 -1
  5. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_validator/fast_validator.py +47 -0
  6. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_fast_validator.py +102 -0
  7. {stac_valid-4.2.0 → stac_valid-4.2.2}/LICENSE +0 -0
  8. {stac_valid-4.2.0 → stac_valid-4.2.2}/setup.cfg +0 -0
  9. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_valid.egg-info/SOURCES.txt +0 -0
  10. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_valid.egg-info/dependency_links.txt +0 -0
  11. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_valid.egg-info/entry_points.txt +0 -0
  12. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_valid.egg-info/requires.txt +0 -0
  13. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_valid.egg-info/top_level.txt +0 -0
  14. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_validator/__init__.py +0 -0
  15. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_validator/batch_validator.py +0 -0
  16. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_validator/stac_validator.py +0 -0
  17. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_validator/utilities.py +0 -0
  18. {stac_valid-4.2.0 → stac_valid-4.2.2}/stac_validator/validate.py +0 -0
  19. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_assets.py +0 -0
  20. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_batch_validator.py +0 -0
  21. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_config.py +0 -0
  22. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_core.py +0 -0
  23. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_custom.py +0 -0
  24. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_default.py +0 -0
  25. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_extensions.py +0 -0
  26. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_header.py +0 -0
  27. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_links.py +0 -0
  28. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_pydantic.py +0 -0
  29. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_recursion.py +0 -0
  30. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_schema_cache.py +0 -0
  31. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_sys_exit.py +0 -0
  32. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_validate_collections.py +0 -0
  33. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_validate_dict.py +0 -0
  34. {stac_valid-4.2.0 → stac_valid-4.2.2}/tests/test_validate_item_collection.py +0 -0
@@ -1,7 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stac_valid
3
- Version: 4.2.0
3
+ Version: 4.2.2
4
4
  Summary: A package to validate STAC files
5
+ Author: James Banting
5
6
  Author-email: Jonathan Healy <jon@healy-hyperspatial.dev>
6
7
  License: Apache-2.0
7
8
  Project-URL: Homepage, https://github.com/stac-utils/stac-validator
@@ -54,6 +55,27 @@ Dynamic: license-file
54
55
  [![PyPI version](https://img.shields.io/pypi/v/stac-validator.svg?color=blue)](https://pypi.org/project/stac-validator/)
55
56
  [![STAC](https://img.shields.io/badge/STAC-1.1.0-blue.svg)](https://github.com/radiantearth/stac-spec/tree/v1.1.0)
56
57
 
58
+
59
+
60
+ > ⚠️ **IMPORTANT NOTICE: PyPI Package Renamed** ⚠️
61
+ >
62
+ > Due to an administrative transition, the PyPI package name for this project has changed. The `stac-validator` package on PyPI is no longer maintained.
63
+ >
64
+ > To get the latest updates, bug fixes, and features (v4.2.0 and beyond), you must now install **`stac-valid`**.
65
+ >
66
+ > ### 🛠️ What you need to do
67
+ >
68
+ > You only need to update your installation command or `requirements.txt`:
69
+ > ```bash
70
+ > # OLD
71
+ > pip install stac-validator
72
+ >
73
+ > # NEW
74
+ > pip install stac-valid
75
+ > ```
76
+ >
77
+ > **Your existing Python code and CLI scripts DO NOT need to change.** > You will still use `import stac_validator` and the `stac-validator` CLI command exactly as you did before.
78
+
57
79
  ## Table of Contents
58
80
 
59
81
  - [Overview](#overview)
@@ -831,6 +853,54 @@ stac.validate_item_collection_dict(item_collection_dict)
831
853
  print(stac.message)
832
854
  ```
833
855
 
856
+ **Fast Validation (High-Speed with Local Caching)**
857
+
858
+ For large FeatureCollections or when you need maximum speed with minimal memory overhead:
859
+
860
+ ```python
861
+ from stac_validator.fast_validator import FastValidator
862
+ import json
863
+
864
+ # Validate a FeatureCollection or single STAC object
865
+ fv = FastValidator("large_collection.json", quiet=True)
866
+ fv.run()
867
+
868
+ # Access validation results via the message attribute
869
+ print(json.dumps(fv.message, indent=2))
870
+
871
+ # Example output:
872
+ # {
873
+ # "path": "large_collection.json",
874
+ # "valid_stac": true,
875
+ # "stac_versions": ["1.0.0", "1.1.0"],
876
+ # "schemas_checked": [
877
+ # "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json",
878
+ # "https://schemas.stacspec.org/v1.1.0/item-spec/json-schema/item.json",
879
+ # "https://stac-extensions.github.io/projection/v1.0.0/schema.json"
880
+ # ],
881
+ # "total_objects": 1000,
882
+ # "valid_objects": 998,
883
+ # "invalid_objects": 2,
884
+ # "setup_time_ms": 145.32,
885
+ # "execution_time_ms": 245.67,
886
+ # "errors": [
887
+ # {
888
+ # "error_message": "STAC Spec Violation: Missing {'rel': 'collection'} in links array.",
889
+ # "affected_items": ["item_1", "item_2"],
890
+ # "count": 2
891
+ # }
892
+ # ]
893
+ # }
894
+
895
+ # Check validity
896
+ if fv.valid:
897
+ print(f"✅ All {fv.message[0]['valid_objects']} items are valid")
898
+ else:
899
+ print(f"❌ {fv.message[0]['invalid_objects']} items failed validation")
900
+ for error in fv.message[0]['errors']:
901
+ print(f" - {error['error_message']}: {error['count']} items affected")
902
+ ```
903
+
834
904
  **Configure Schema Cache Size**
835
905
 
836
906
  ```python
@@ -13,6 +13,27 @@
13
13
  [![PyPI version](https://img.shields.io/pypi/v/stac-validator.svg?color=blue)](https://pypi.org/project/stac-validator/)
14
14
  [![STAC](https://img.shields.io/badge/STAC-1.1.0-blue.svg)](https://github.com/radiantearth/stac-spec/tree/v1.1.0)
15
15
 
16
+
17
+
18
+ > ⚠️ **IMPORTANT NOTICE: PyPI Package Renamed** ⚠️
19
+ >
20
+ > Due to an administrative transition, the PyPI package name for this project has changed. The `stac-validator` package on PyPI is no longer maintained.
21
+ >
22
+ > To get the latest updates, bug fixes, and features (v4.2.0 and beyond), you must now install **`stac-valid`**.
23
+ >
24
+ > ### 🛠️ What you need to do
25
+ >
26
+ > You only need to update your installation command or `requirements.txt`:
27
+ > ```bash
28
+ > # OLD
29
+ > pip install stac-validator
30
+ >
31
+ > # NEW
32
+ > pip install stac-valid
33
+ > ```
34
+ >
35
+ > **Your existing Python code and CLI scripts DO NOT need to change.** > You will still use `import stac_validator` and the `stac-validator` CLI command exactly as you did before.
36
+
16
37
  ## Table of Contents
17
38
 
18
39
  - [Overview](#overview)
@@ -790,6 +811,54 @@ stac.validate_item_collection_dict(item_collection_dict)
790
811
  print(stac.message)
791
812
  ```
792
813
 
814
+ **Fast Validation (High-Speed with Local Caching)**
815
+
816
+ For large FeatureCollections or when you need maximum speed with minimal memory overhead:
817
+
818
+ ```python
819
+ from stac_validator.fast_validator import FastValidator
820
+ import json
821
+
822
+ # Validate a FeatureCollection or single STAC object
823
+ fv = FastValidator("large_collection.json", quiet=True)
824
+ fv.run()
825
+
826
+ # Access validation results via the message attribute
827
+ print(json.dumps(fv.message, indent=2))
828
+
829
+ # Example output:
830
+ # {
831
+ # "path": "large_collection.json",
832
+ # "valid_stac": true,
833
+ # "stac_versions": ["1.0.0", "1.1.0"],
834
+ # "schemas_checked": [
835
+ # "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json",
836
+ # "https://schemas.stacspec.org/v1.1.0/item-spec/json-schema/item.json",
837
+ # "https://stac-extensions.github.io/projection/v1.0.0/schema.json"
838
+ # ],
839
+ # "total_objects": 1000,
840
+ # "valid_objects": 998,
841
+ # "invalid_objects": 2,
842
+ # "setup_time_ms": 145.32,
843
+ # "execution_time_ms": 245.67,
844
+ # "errors": [
845
+ # {
846
+ # "error_message": "STAC Spec Violation: Missing {'rel': 'collection'} in links array.",
847
+ # "affected_items": ["item_1", "item_2"],
848
+ # "count": 2
849
+ # }
850
+ # ]
851
+ # }
852
+
853
+ # Check validity
854
+ if fv.valid:
855
+ print(f"✅ All {fv.message[0]['valid_objects']} items are valid")
856
+ else:
857
+ print(f"❌ {fv.message[0]['invalid_objects']} items failed validation")
858
+ for error in fv.message[0]['errors']:
859
+ print(f" - {error['error_message']}: {error['count']} items affected")
860
+ ```
861
+
793
862
  **Configure Schema Cache Size**
794
863
 
795
864
  ```python
@@ -4,9 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "stac_valid"
7
- version = "4.2.0"
7
+ version = "4.2.2"
8
8
  description = "A package to validate STAC files"
9
9
  authors = [
10
+ {name = "James Banting"},
10
11
  {name = "Jonathan Healy", email = "jon@healy-hyperspatial.dev"}
11
12
  ]
12
13
  license = {text = "Apache-2.0"}
@@ -1,7 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stac_valid
3
- Version: 4.2.0
3
+ Version: 4.2.2
4
4
  Summary: A package to validate STAC files
5
+ Author: James Banting
5
6
  Author-email: Jonathan Healy <jon@healy-hyperspatial.dev>
6
7
  License: Apache-2.0
7
8
  Project-URL: Homepage, https://github.com/stac-utils/stac-validator
@@ -54,6 +55,27 @@ Dynamic: license-file
54
55
  [![PyPI version](https://img.shields.io/pypi/v/stac-validator.svg?color=blue)](https://pypi.org/project/stac-validator/)
55
56
  [![STAC](https://img.shields.io/badge/STAC-1.1.0-blue.svg)](https://github.com/radiantearth/stac-spec/tree/v1.1.0)
56
57
 
58
+
59
+
60
+ > ⚠️ **IMPORTANT NOTICE: PyPI Package Renamed** ⚠️
61
+ >
62
+ > Due to an administrative transition, the PyPI package name for this project has changed. The `stac-validator` package on PyPI is no longer maintained.
63
+ >
64
+ > To get the latest updates, bug fixes, and features (v4.2.0 and beyond), you must now install **`stac-valid`**.
65
+ >
66
+ > ### 🛠️ What you need to do
67
+ >
68
+ > You only need to update your installation command or `requirements.txt`:
69
+ > ```bash
70
+ > # OLD
71
+ > pip install stac-validator
72
+ >
73
+ > # NEW
74
+ > pip install stac-valid
75
+ > ```
76
+ >
77
+ > **Your existing Python code and CLI scripts DO NOT need to change.** > You will still use `import stac_validator` and the `stac-validator` CLI command exactly as you did before.
78
+
57
79
  ## Table of Contents
58
80
 
59
81
  - [Overview](#overview)
@@ -831,6 +853,54 @@ stac.validate_item_collection_dict(item_collection_dict)
831
853
  print(stac.message)
832
854
  ```
833
855
 
856
+ **Fast Validation (High-Speed with Local Caching)**
857
+
858
+ For large FeatureCollections or when you need maximum speed with minimal memory overhead:
859
+
860
+ ```python
861
+ from stac_validator.fast_validator import FastValidator
862
+ import json
863
+
864
+ # Validate a FeatureCollection or single STAC object
865
+ fv = FastValidator("large_collection.json", quiet=True)
866
+ fv.run()
867
+
868
+ # Access validation results via the message attribute
869
+ print(json.dumps(fv.message, indent=2))
870
+
871
+ # Example output:
872
+ # {
873
+ # "path": "large_collection.json",
874
+ # "valid_stac": true,
875
+ # "stac_versions": ["1.0.0", "1.1.0"],
876
+ # "schemas_checked": [
877
+ # "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json",
878
+ # "https://schemas.stacspec.org/v1.1.0/item-spec/json-schema/item.json",
879
+ # "https://stac-extensions.github.io/projection/v1.0.0/schema.json"
880
+ # ],
881
+ # "total_objects": 1000,
882
+ # "valid_objects": 998,
883
+ # "invalid_objects": 2,
884
+ # "setup_time_ms": 145.32,
885
+ # "execution_time_ms": 245.67,
886
+ # "errors": [
887
+ # {
888
+ # "error_message": "STAC Spec Violation: Missing {'rel': 'collection'} in links array.",
889
+ # "affected_items": ["item_1", "item_2"],
890
+ # "count": 2
891
+ # }
892
+ # ]
893
+ # }
894
+
895
+ # Check validity
896
+ if fv.valid:
897
+ print(f"✅ All {fv.message[0]['valid_objects']} items are valid")
898
+ else:
899
+ print(f"❌ {fv.message[0]['invalid_objects']} items failed validation")
900
+ for error in fv.message[0]['errors']:
901
+ print(f" - {error['error_message']}: {error['count']} items affected")
902
+ ```
903
+
834
904
  **Configure Schema Cache Size**
835
905
 
836
906
  ```python
@@ -132,6 +132,7 @@ class FastValidator:
132
132
  self.quiet = quiet
133
133
  self.valid = True
134
134
  self.verbose = verbose
135
+ self.message: List[Dict[str, Any]] = []
135
136
  QUIET_MODE = quiet
136
137
 
137
138
  def run(self):
@@ -199,6 +200,8 @@ class FastValidator:
199
200
  valid_count = 0
200
201
  invalid_count = 0
201
202
  error_registry: Dict[str, List[str]] = {}
203
+ stac_versions_found: set = set()
204
+ schemas_checked: set = set()
202
205
 
203
206
  for index, item in enumerate(items_to_validate):
204
207
  # Determine specific STAC attributes for this object
@@ -206,11 +209,32 @@ class FastValidator:
206
209
  stac_version = item.get("stac_version", "1.0.0")
207
210
  extensions = item.get("stac_extensions", [])
208
211
 
212
+ # Track versions and schemas
213
+ stac_versions_found.add(stac_version)
214
+
209
215
  # Map Feature->Item, others keep their type
210
216
  actual_type = (
211
217
  "Item" if item.get("type") == "Feature" else item.get("type", "Catalog")
212
218
  )
213
219
 
220
+ # Build schema URI for this object type
221
+ stac_type_lower = actual_type.lower()
222
+ if stac_type_lower in ["item", "feature"]:
223
+ base_schema = f"https://schemas.stacspec.org/v{stac_version}/item-spec/json-schema/item.json"
224
+ elif stac_type_lower == "collection":
225
+ base_schema = f"https://schemas.stacspec.org/v{stac_version}/collection-spec/json-schema/collection.json"
226
+ elif stac_type_lower == "catalog":
227
+ base_schema = f"https://schemas.stacspec.org/v{stac_version}/catalog-spec/json-schema/catalog.json"
228
+ else:
229
+ base_schema = ""
230
+
231
+ if base_schema:
232
+ schemas_checked.add(base_schema)
233
+
234
+ # Track extensions
235
+ for ext in extensions:
236
+ schemas_checked.add(ext)
237
+
214
238
  # --- Setup Timer ---
215
239
  t0 = time.perf_counter()
216
240
  try:
@@ -309,4 +333,27 @@ class FastValidator:
309
333
  sample_ids += f" ... (and {count - 3} more)"
310
334
  click.echo(f" Examples: {sample_ids}")
311
335
 
336
+ # Populate the message attribute for API usage (similar to StacValidate)
337
+ self.message = [
338
+ {
339
+ "path": self.stac_file,
340
+ "valid_stac": self.valid,
341
+ "stac_versions": sorted(list(stac_versions_found)),
342
+ "schemas_checked": sorted(list(schemas_checked)),
343
+ "total_objects": len(items_to_validate),
344
+ "valid_objects": valid_count,
345
+ "invalid_objects": invalid_count,
346
+ "setup_time_ms": total_setup_ms,
347
+ "execution_time_ms": total_exec_ms,
348
+ "errors": [
349
+ {
350
+ "error_message": err_msg,
351
+ "affected_items": affected_ids,
352
+ "count": len(affected_ids),
353
+ }
354
+ for err_msg, affected_ids in error_registry.items()
355
+ ],
356
+ }
357
+ ]
358
+
312
359
  click.echo("\n")
@@ -304,3 +304,105 @@ class TestFastValidatorPerformance:
304
304
  fv = FastValidator(str(fc_path), quiet=True)
305
305
  fv.run()
306
306
  assert fv.valid is True
307
+
308
+ def test_message_attribute_structure(self, valid_item):
309
+ """Test that the message attribute has the correct structure."""
310
+ fv = FastValidator(valid_item, quiet=True)
311
+ fv.run()
312
+
313
+ # Verify message is a list with one dict
314
+ assert isinstance(fv.message, list)
315
+ assert len(fv.message) == 1
316
+
317
+ msg = fv.message[0]
318
+
319
+ # Verify required fields exist
320
+ assert "path" in msg
321
+ assert "valid_stac" in msg
322
+ assert "stac_versions" in msg
323
+ assert "schemas_checked" in msg
324
+ assert "total_objects" in msg
325
+ assert "valid_objects" in msg
326
+ assert "invalid_objects" in msg
327
+ assert "setup_time_ms" in msg
328
+ assert "execution_time_ms" in msg
329
+ assert "errors" in msg
330
+
331
+ # Verify field types
332
+ assert isinstance(msg["path"], str)
333
+ assert isinstance(msg["valid_stac"], bool)
334
+ assert isinstance(msg["stac_versions"], list)
335
+ assert isinstance(msg["schemas_checked"], list)
336
+ assert isinstance(msg["total_objects"], int)
337
+ assert isinstance(msg["valid_objects"], int)
338
+ assert isinstance(msg["invalid_objects"], int)
339
+ assert isinstance(msg["setup_time_ms"], float)
340
+ assert isinstance(msg["execution_time_ms"], float)
341
+ assert isinstance(msg["errors"], list)
342
+
343
+ def test_message_attribute_valid_items(self, valid_feature_collection):
344
+ """Test message attribute for valid items."""
345
+ fv = FastValidator(valid_feature_collection, quiet=True)
346
+ fv.run()
347
+
348
+ msg = fv.message[0]
349
+
350
+ # For valid items
351
+ assert msg["valid_stac"] is True
352
+ assert msg["total_objects"] == 5
353
+ assert msg["valid_objects"] == 5
354
+ assert msg["invalid_objects"] == 0
355
+ assert len(msg["errors"]) == 0
356
+
357
+ # Verify versions and schemas are tracked
358
+ assert len(msg["stac_versions"]) > 0
359
+ assert len(msg["schemas_checked"]) > 0
360
+ assert "1.0.0" in msg["stac_versions"]
361
+
362
+ def test_message_attribute_invalid_items(self, tmp_path):
363
+ """Test message attribute for invalid items."""
364
+ fc_path = tmp_path / "invalid_fc.json"
365
+ fc_data = {
366
+ "type": "FeatureCollection",
367
+ "features": [
368
+ {
369
+ "stac_version": "1.0.0",
370
+ "type": "Feature",
371
+ "id": "item-1",
372
+ "geometry": None,
373
+ "properties": {"datetime": "2023-01-01T00:00:00Z"},
374
+ "links": [{"rel": "self", "href": "http://example.com"}],
375
+ "assets": {},
376
+ },
377
+ {
378
+ "stac_version": "1.0.0",
379
+ "type": "Feature",
380
+ "id": "item-2",
381
+ "geometry": None,
382
+ # Missing required 'properties' field
383
+ "links": [{"rel": "self", "href": "http://example.com"}],
384
+ "assets": {},
385
+ },
386
+ ],
387
+ }
388
+ fc_path.write_text(json.dumps(fc_data))
389
+
390
+ fv = FastValidator(str(fc_path), quiet=True)
391
+ fv.run()
392
+
393
+ msg = fv.message[0]
394
+
395
+ # For mixed valid/invalid items
396
+ assert msg["valid_stac"] is False
397
+ assert msg["total_objects"] == 2
398
+ assert msg["valid_objects"] == 1
399
+ assert msg["invalid_objects"] == 1
400
+ assert len(msg["errors"]) > 0
401
+
402
+ # Verify error structure
403
+ for error in msg["errors"]:
404
+ assert "error_message" in error
405
+ assert "affected_items" in error
406
+ assert "count" in error
407
+ assert isinstance(error["affected_items"], list)
408
+ assert error["count"] == len(error["affected_items"])
File without changes
File without changes