Repository: stac-utils/stac-check (language: python)

Issue:
Reorg for version 1.0.0



Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index d8b03be..76b2318 100644
--- a/README.md
+++ b/README.md
@@ -20,54 +20,79 @@ Validator: pystac 1.1.0
     Recursive: Validate all assets in a collection or catalog
 
 Valid COLLECTION: True
+
 Schemas validated: 
     https://cdn.staclint.com/v0.9.0/collection.json
 
+STAC Best Practices: 
+    Object should be called 'collection.json' not 'landsat-collection.json'
+
+    A STAC collection should contain a summaries field
+    It is recommended to store information like eo:bands in summaries
+
+    Links in catalogs and collections should always have a 'title' field
+
+
 Recursive validation has failed!
-Validation error message: 
+Recursive validation error message: 
     Exception Could not read uri https://landsat-stac.s3.amazonaws.com/landsat-8-l1/paths/catalog.json
 
-WARNING: STAC Best Practices asks for a summaries field in a STAC collection
-    https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md
-
 This object has 4 links
 ```
 
 ``` stac_check sample_files/0.9.0/landsat8-sample.json```
 
 <pre><b>stac-check: STAC spec validaton and linting tool</b>
+
 Please upgrade from version 0.9.0 to version 1.0.0!
 
-Validator: stac-validator 2.4.0
+Validator: stac-validator 2.3.0
 
 Valid ITEM: True
 
-STAC Best Practices: Item names should match their ids
-    'landsat8-sample' not equal to 'LC81530252014153LGN00'
-
 Schemas validated: 
     https://cdn.staclint.com/v0.9.0/extension/eo.json
     https://cdn.staclint.com/v0.9.0/extension/view.json
     https://cdn.staclint.com/v0.9.0/item.json
 
+STAC Best Practices: 
+    Item name 'LC81530252014153LGN00' should only contain Searchable identifiers
+    Identifiers should consist of only lowercase characters, numbers, '_', and '-'
+    https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#searchable-identifiers
+
+    Item file names should match their ids: 'landsat8-sample' not equal to 'LC81530252014153LGN00
+
+    A link to 'self' in links is strongly recommended
+
+
 This object has 4 links
 </pre>
 
 ``` stac_check sample_files/1.0.0/core-item.json --assets```    
 <pre>
 <b>stac-check: STAC spec validaton and linting tool</b>
+
 Thanks for using STAC version 1.0.0!
 
-Validator: stac-validator 2.4.0
+Validator: stac-validator 2.3.0
 
 Valid ITEM: True
 
-STAC Best Practices: Item names should match their ids
-    'core-item' not equal to '20201211_223832_CS2'
-
 Schemas validated: 
     https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json
 
+STAC Best Practices: 
+    Item name '20201211_223832_CS2' should only contain Searchable identifiers
+    Identifiers should consist of only lowercase characters, numbers, '_', and '-'
+    https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#searchable-identifiers
+
+    Item file names should match their ids: 'core-item' not equal to '20201211_223832_CS2
+
+    Please avoid setting the datetime field to null, many clients search on this field
+
+    A link to 'self' in links is strongly recommended
+
+
 No ASSET format errors!
 
 ASSET request errors: 
@@ -81,18 +106,28 @@ This object has 4 links
 ``` stac_check sample_files/1.0.0/core-item-bad-links.json --links --assets```    
 <pre>
 <b>stac-check: STAC spec validaton and linting tool</b>
+
 Thanks for using STAC version 1.0.0!
 
-Validator: stac-validator 2.4.0
+Validator: stac-validator 2.3.0
 
 Valid ITEM: True
 
-STAC Best Practices: Item names should match their ids
-    'core-item-bad-links' not equal to '20201211_223832_CS2'
-
 Schemas validated: 
     https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json
 
+STAC Best Practices: 
+    Item name '20201211_223832_CS2' should only contain Searchable identifiers
+    Identifiers should consist of only lowercase characters, numbers, '_', and '-'
+    https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#searchable-identifiers
+
+    Item file names should match their ids: 'core-item-bad-links' not equal to '20201211_223832_CS2
+
+    Please avoid setting the datetime field to null, many clients search on this field
+
+    A link to 'self' in links is strongly recommended
+
+
 ASSET format errors: 
     https:/storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg
 
@@ -110,18 +145,22 @@ LINK request errors:
 This object has 4 links
 </pre>
   
-  
-    
 ``` stac_check sample_files/0.9.0/bad-item.json```    
 <pre>
 <b>stac-check: STAC spec validaton and linting tool</b>
+
 Please upgrade from version 0.9.0 to version 1.0.0!
 
-Validator: stac-validator 2.4.0
+Validator: stac-validator 2.3.0
 
 Valid : False
+
 Schemas validated: 
     https://cdn.staclint.com/v0.9.0/item.json
+
+STAC Best Practices: 
+    A link to 'self' in links is strongly recommended
+
 Validation error type: 
     ValidationError
 Validation error message: 
diff --git a/stac-best-practices.md b/best-practices.md
similarity index 100%
rename from stac-best-practices.md
rename to best-practices.md
diff --git a/setup.py b/setup.py
index 9fdceb2..59df321 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
 """
 from setuptools import setup, find_packages
 
-__version__ = "0.2.0"
+__version__ = "1.0.0"
 
 with open("README.md", "r") as fh:
     long_description = fh.read()
diff --git a/stac_check/cli.py b/stac_check/cli.py
index bd00e85..f3d9747 100644
--- a/stac_check/cli.py
+++ b/stac_check/cli.py
@@ -24,9 +24,9 @@ def cli_message(linter):
     click.secho()
 
     if linter.version == "1.0.0":
-        click.secho(linter.update_msg, fg='green')
+        click.secho(linter.set_update_message(), fg='green')
     else:
-        click.secho(linter.update_msg, fg='red')
+        click.secho(linter.set_update_message(), fg='red')
 
     click.secho()
 
diff --git a/stac_check/lint.py b/stac_check/lint.py
index e98e2f6..f580b12 100644
--- a/stac_check/lint.py
+++ b/stac_check/lint.py
@@ -5,7 +5,6 @@
 from dataclasses import dataclass
 import pystac
 import requests
-from urllib.parse import urlparse
 
 @dataclass
 class Linter:
@@ -17,10 +16,9 @@ class Linter:
     def __post_init__(self):
         self.data = self.load_data(self.item)
         self.message = self.validate_file(self.item)
-        self.asset_type = self.check_asset_type()
-        self.version = self.check_version()
+        self.asset_type = self.message["asset_type"] if "asset_type" in self.message else ""
+        self.version = self.message["version"] if "version" in self.message else ""
         self.validator_version = "2.3.0"
-        self.update_msg = self.set_update_message()
         self.valid_stac = self.message["valid_stac"]
         self.error_type = self.check_error_type()
         self.error_msg = self.check_error_message()
@@ -28,19 +26,11 @@ def __post_init__(self):
         self.invalid_asset_request = self.check_links_assets(10, "assets", "request") if self.assets else None
         self.invalid_link_format = self.check_links_assets(10, "links", "format") if self.links else None
         self.invalid_link_request = self.check_links_assets(10, "links", "request") if self.links else None
-        self.schema = self.check_schema()
-        self.summaries = self.check_summaries()
-        self.bloated_links = self.get_bloated_links()
-        self.bloated_metadata = self.get_bloated_metadata()
+        self.schema = self.message["schema"] if "schema" in self.message else []
         self.recursive_error_msg = ""
-        self.datetime_null = self.check_datetime()
-        self.unlocated = self.check_unlocated()
-        self.geometry = self.check_geometry()
         self.validate_all = self.recursive_validation(self.load_data(self.item))
-        self.object_id = self.return_id()
-        self.file_name = self.get_file_name()
-        self.searchable_identifiers = self.check_searchable_identifiers()
-        self.percent_encoded = self.check_percent_encoded()
+        self.object_id = self.data["id"] if "id" in self.data else ""
+        self.file_name = os.path.basename(self.item).split('.')[0]
         self.best_practices_msg = self.create_best_practices_msg()
 
     def load_data(self, file):
@@ -67,24 +57,6 @@ def recursive_validation(self, file):
                 self.recursive_error_msg = f"Exception {str(e)}"
                 return False
 
-    def check_asset_type(self):
-        if "asset_type" in self.message:
-            return self.message["asset_type"]
-        else:
-            return ""
-
-    def check_schema(self):
-        if "schema" in self.message:
-            return self.message["schema"]
-        else:
-            return []
-
-    def check_version(self):
-        if "version" in self.message:
-            return self.message["version"]
-        else:
-            return ""
-
     def set_update_message(self):
         if self.version != "1.0.0":
             return f"Please upgrade from version {self.version} to version 1.0.0!"
@@ -115,23 +87,18 @@ def check_error_message(self):
             return ""
 
     def check_summaries(self):
-        return "summaries" in self.data
+        if self.asset_type == "COLLECTION":
+            return "summaries" in self.data
 
-    def get_bloated_links(self):
+    def check_bloated_links(self):
         if "links" in self.data:
             return len(self.data["links"]) > 20
 
-    def get_bloated_metadata(self):
+    def check_bloated_metadata(self):
         if "properties" in self.data:
             return len(self.data["properties"].keys()) > 20
 
-    def return_id(self):
-        if "id" in self.data:
-            return self.data["id"]
-        else:
-            return ""
-
-    def check_datetime(self):
+    def check_datetime_null(self):
         if "properties" in self.data:
             if "datetime" in self.data["properties"]:
                 if self.data["properties"]["datetime"] == None:
@@ -143,12 +110,9 @@ def check_unlocated(self):
         if "geometry" in self.data:
             return self.data["geometry"] is None and self.data["bbox"] is not None
 
-    def check_geometry(self):
+    def check_geometry_null(self):
         if "geometry" in self.data:
-            return self.data["geometry"] is not None
-
-    def get_file_name(self):
-        return os.path.basename(self.item).split('.')[0]
+            return self.data["geometry"] is None
 
     def check_searchable_identifiers(self):
         if self.asset_type == "ITEM": 
@@ -204,14 +168,14 @@ def create_best_practices_msg(self):
         best_practices.append(base_string)
 
         # best practices - item ids should only contain searchable identifiers
-        if self.searchable_identifiers == False: 
+        if self.check_searchable_identifiers() == False: 
             string_1 = f"    Item name '{self.object_id}' should only contain Searchable identifiers"
             string_2 = f"    Identifiers should consist of only lowercase characters, numbers, '_', and '-'"
             string_3 = f"    https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#searchable-identifiers"
             best_practices.extend([string_1, string_2, string_3, ""])  
 
         # best practices - item ids should not contain ':' or '/' characters
-        if self.percent_encoded:
+        if self.check_percent_encoded():
             string_1 = f"    Item name '{self.object_id}' should not contain ':' or '/'"
             string_2 = f"    https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#item-ids"
             best_practices.extend([string_1, string_2, ""])
@@ -227,34 +191,34 @@ def create_best_practices_msg(self):
             best_practices.extend([string_1, ""])
 
         # best practices - collections should contain summaries
-        if self.asset_type == "COLLECTION" and self.summaries == False:
+        if self.check_summaries() == False:
             string_1 = f"    A STAC collection should contain a summaries field"
             string_2 = f"    It is recommended to store information like eo:bands in summaries"
             best_practices.extend([string_1, string_2, ""])
 
         # best practices - datetime files should not be set to null
-        if self.datetime_null:
+        if self.check_datetime_null():
             string_1 = f"    Please avoid setting the datetime field to null, many clients search on this field"
             best_practices.extend([string_1, ""])
 
         # best practices - check unlocated items to make sure bbox field is not set
-        if self.unlocated:
+        if self.check_unlocated():
             string_1 = f"    Unlocated item. Please avoid setting the bbox field when geometry is set to null"
             best_practices.extend([string_1, ""])
 
         # best practices - recommend items have a geometry
-        if not self.geometry and self.asset_type == "ITEM":
+        if self.check_geometry_null():
             string_1 = f"    All items should have a geometry field. STAC is not meant for non-spatial data"
             best_practices.extend([string_1, ""])
 
         # check to see if there are too many links
-        if self.bloated_links:
+        if self.check_bloated_links():
             string_1 = f"    You have {len(self.data['links'])} links. Please consider using sub-collections or sub-catalogs"
             string_2 = f"    https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#catalog--collection-practices"
             best_practices.extend([string_1, string_2, ""])
 
         # best practices - check for bloated metadata in properties
-        if self.bloated_metadata:
+        if self.check_bloated_metadata():
             string_1 = f"    You have {len(self.data['properties'])} properties. Please consider using links to avoid bloated metadata"
             best_practices.extend([string_1, ""])
 


Test patch:
diff --git a/tests/test_lint.py b/tests/test_lint.py
index 434a06a..2730aa9 100644
--- a/tests/test_lint.py
+++ b/tests/test_lint.py
@@ -77,7 +77,7 @@ def test_linter_collection():
     assert linter.version == "1.0.0"
     assert linter.valid_stac == True
     assert linter.asset_type == "COLLECTION"
-    assert linter.summaries == True
+    assert linter.check_summaries() == True
 
 def test_linter_collection_no_summaries():
     file = "sample_files/1.0.0/collection-no-summaries.json"
@@ -85,7 +85,7 @@ def test_linter_collection_no_summaries():
     assert linter.version == "1.0.0"
     assert linter.valid_stac == True
     assert linter.asset_type == "COLLECTION"
-    assert linter.summaries == False
+    assert linter.check_summaries() == False
     assert linter.best_practices_msg == [
         "STAC Best Practices: ",
         "    Object should be called 'collection.json' not 'collection-no-summaries.json'",
@@ -101,7 +101,7 @@ def test_linter_catalog():
     assert linter.version == "1.0.0"
     assert linter.valid_stac == True
     assert linter.asset_type == "CATALOG"
-    assert linter.bloated_links == False
+    assert linter.check_bloated_links() == False
 
 def test_linter_collection_recursive_remote():
     file = "https://raw.githubusercontent.com/stac-utils/pystac/main/tests/data-files/examples/0.9.0/collection-spec/examples/landsat-collection.json"
@@ -126,28 +126,28 @@ def test_linter_collection_catalog_id():
 def test_linter_item_id_format_best_practices():
     file = "sample_files/1.0.0/core-item-invalid-id.json"
     linter = Linter(file)
-    assert linter.searchable_identifiers == False
-    assert linter.percent_encoded == True
+    assert linter.check_searchable_identifiers() == False
+    assert linter.check_percent_encoded() == True
 
 def test_datetime_set_to_null():
     file = "sample_files/1.0.0/core-item-null-datetime.json"
     linter = Linter(file)
-    assert linter.datetime_null == True
+    assert linter.check_datetime_null()== True
 
 def test_unlocated_item():
     file = "sample_files/1.0.0/core-item-unlocated.json"
     linter = Linter(file)
-    assert linter.unlocated == True
-    assert linter.geometry == False
+    assert linter.check_unlocated() == True
+    assert linter.check_geometry_null() == True
 
 def test_bloated_item():
     file = "sample_files/1.0.0/core-item-bloated.json"
     linter = Linter(file)
 
-    assert linter.bloated_metadata == True
+    assert linter.check_bloated_metadata() == True
     assert len(linter.data["properties"]) > 20
 
-    assert linter.bloated_links == True
+    assert linter.check_bloated_links() == True
     assert len(linter.data["links"]) > 20
 
 def test_small_thumbnail():