From 1638b9cb990b16e8565880b329691469d8e4e2d6 Mon Sep 17 00:00:00 2001 From: Vincent Privat Date: Mon, 2 Dec 2024 18:07:14 +0100 Subject: [PATCH 1/4] Allow to provide HTTP headers, Configure whether to open URLs when validating assets --- CHANGELOG.md | 5 +++++ README.md | 39 ++++++++++++++++++++++++++++++++++----- stac_check/cli.py | 21 +++++++++++++++++++-- stac_check/lint.py | 35 +++++++++++++++++++++++++++++------ 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e76608..a6a092a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is (loosely) based on [Keep a Changelog](http://keepachangelog.com/) ## Unreleased +### Added + +- Allow to provide HTTP headers ([#114](https://github.com/stac-utils/stac-check/pull/114)) +- Configure whether to open URLs when validating assets ([#114](https://github.com/stac-utils/stac-check/pull/114)) + ### Changed - No longer use the deprecated pkg-resources package. diff --git a/README.md b/README.md index 66337ac..6735872 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ Options: argument to get full recursion. Ignored if `recursive == False`. -r, --recursive Recursively validate all related stac objects. + --no-assets-urls Disables the opening of href links when validating assets + (enabled by default). + --header KEY VALUE HTTP header to include in the requests. Can be used + multiple times. --help Show this message and exit. Show this message and exit. ``` --- @@ -62,7 +66,7 @@ stac-check: STAC spec validation and linting tool Please upgrade from version 0.9.0 to version 1.0.0! -Validator: stac-validator 3.1.0 +Validator: stac-validator 3.5.0 Recursive: Validate all assets in a collection or catalog @@ -102,7 +106,7 @@ Error Message: Expecting value: line 1 column 1 (char 0) Please upgrade from version 0.9.0 to version 1.0.0! -Validator: stac-validator 2.3.0 +Validator: stac-validator 3.5.0 Valid ITEM: True @@ -130,7 +134,7 @@ This object has 4 links Thanks for using STAC version 1.0.0! -Validator: stac-validator 2.3.0 +Validator: stac-validator 3.5.0 Valid ITEM: True @@ -165,7 +169,7 @@ This object has 4 links Thanks for using STAC version 1.0.0! -Validator: stac-validator 2.3.0 +Validator: stac-validator 3.5.0 Valid ITEM: True @@ -207,7 +211,7 @@ This object has 4 links Please upgrade from version 0.9.0 to version 1.0.0! -Validator: stac-validator 2.3.0 +Validator: stac-validator 3.5.0 Valid : False @@ -224,6 +228,31 @@ Validation error message: This object has 5 links + +``` stac-check https://stac-catalog.eu/collections/sentinel-s2-l2a/items/item1 --assets --no-assets-urls --header x-api-key $MY_API_KEY --header foo bar``` +
+stac-check: STAC spec validation and linting tool
+
+Thanks for using STAC version 1.0.0!
+
+Validator: stac-validator 3.5.0
+
+Valid ITEM: True
+
+Schemas validated: 
+    https://stac-extensions.github.io/timestamps/v1.1.0/schema.json
+    https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json
+
+STAC Best Practices: 
+    A STAC collection should contain a summaries field
+    It is recommended to store information like eo:bands in summaries
+
+
+No ASSET format errors!
+
+No ASSET request errors!
+This object has 4 links
+
--- ### Create local docs in the /docs folder `$ pdoc --html --output-dir pdoc stac_check --force` diff --git a/stac_check/cli.py b/stac_check/cli.py index b9c423e..7005834 100644 --- a/stac_check/cli.py +++ b/stac_check/cli.py @@ -178,12 +178,29 @@ def cli_message(linter: Linter) -> None: @click.option( "-l", "--links", is_flag=True, help="Validate links for format and response." ) +@click.option( + "--no-assets-urls", + is_flag=True, + help="Disables the opening of href links when validating assets (enabled by default).", +) +@click.option( + "--header", + type=(str, str), + multiple=True, + help="HTTP header to include in the requests. Can be used multiple times.", +) @click.command() @click.argument("file") @click.version_option(version=importlib.metadata.distribution("stac-check").version) -def main(file, recursive, max_depth, assets, links): +def main(file, recursive, max_depth, assets, links, no_assets_urls, header): linter = Linter( - file, assets=assets, links=links, recursive=recursive, max_depth=max_depth + file, + assets=assets, + links=links, + recursive=recursive, + max_depth=max_depth, + assets_open_urls=not no_assets_urls, + headers=dict(header), ) intro_message(linter) if recursive > 0: diff --git a/stac_check/lint.py b/stac_check/lint.py index 61e9731..b0e0a46 100644 --- a/stac_check/lint.py +++ b/stac_check/lint.py @@ -2,7 +2,7 @@ import importlib.resources import json import os -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import Any, Dict, List, Optional, Union import requests @@ -25,6 +25,8 @@ class Linter: links (bool, optional): A boolean value indicating whether to validate links. Defaults to False. recursive (bool, optional): A boolean value indicating whether to perform recursive validation. Defaults to False. max_depth (Optional[int], optional): An optional integer indicating the maximum depth to validate recursively. Defaults to None. + assets_open_urls (bool): Whether to open assets URLs when validating assets. Defaults to True. + headers (dict): HTTP headers to include in the requests. Attributes: data (dict): A dictionary representing the STAC JSON file. @@ -126,6 +128,8 @@ def check_summaries(self) -> bool: links: bool = False recursive: bool = False max_depth: Optional[int] = None + assets_open_urls: bool = True + headers: dict = field(default_factory=dict) def __post_init__(self): self.data = self.load_data(self.item) @@ -236,7 +240,7 @@ def load_data(self, file: Union[str, Dict]) -> Dict: if isinstance(file, str): if is_valid_url(file): - resp = requests.get(file) + resp = requests.get(file, headers=self.headers) data = resp.json() else: with open(file) as json_file: @@ -260,10 +264,18 @@ def validate_file(self, file: Union[str, dict]) -> Dict[str, Any]: ValueError: If `file` is not a valid file path or STAC dictionary. """ if isinstance(file, str): - stac = StacValidate(file, links=self.links, assets=self.assets) + stac = StacValidate( + file, + links=self.links, + assets=self.assets, + assets_open_urls=self.assets_open_urls, + headers=self.headers, + ) stac.run() elif isinstance(file, dict): - stac = StacValidate() + stac = StacValidate( + assets_open_urls=self.assets_open_urls, headers=self.headers + ) stac.validate_dict(file) else: raise ValueError("Input must be a file path or STAC dictionary.") @@ -284,10 +296,21 @@ def recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str: """ if self.recursive: if isinstance(file, str): - stac = StacValidate(file, recursive=True, max_depth=self.max_depth) + stac = StacValidate( + file, + recursive=True, + max_depth=self.max_depth, + assets_open_urls=self.assets_open_urls, + headers=self.headers, + ) stac.run() else: - stac = StacValidate(recursive=True, max_depth=self.max_depth) + stac = StacValidate( + recursive=True, + max_depth=self.max_depth, + assets_open_urls=self.assets_open_urls, + headers=self.headers, + ) stac.validate_dict(file) return stac.message else: From 2bd40d76eb454b1fa86abfa72f5fa5de7b15a086 Mon Sep 17 00:00:00 2001 From: Vincent Privat Date: Mon, 13 Jan 2025 16:22:07 +0100 Subject: [PATCH 2/4] Display 'No ASSET request errors\!' only when opening asset URLs --- README.md | 1 - stac_check/cli.py | 17 +++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6735872..59ce8a8 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,6 @@ STAC Best Practices: No ASSET format errors! -No ASSET request errors! This object has 4 links --- diff --git a/stac_check/cli.py b/stac_check/cli.py index 7005834..c2a5c93 100644 --- a/stac_check/cli.py +++ b/stac_check/cli.py @@ -6,13 +6,16 @@ from .logo import logo -def link_asset_message(link_list: list, type: str, format: str) -> None: +def link_asset_message( + link_list: list, type: str, format: str, healthy_msg: bool +) -> None: """Prints a list of links or assets and any errors associated with them. Args: link_list (list): A list of links or assets. type (str): The type of link or asset being processed. format (str): The format or request being used. + healthy_msg (bool): Whether to display "No TYPE errors!" or not Returns: None. @@ -21,7 +24,7 @@ def link_asset_message(link_list: list, type: str, format: str) -> None: click.secho(f"{type.upper()} {format} errors: ", fg="red") for asset in link_list: click.secho(f" {asset}") - else: + elif healthy_msg: click.secho(f"No {type.upper()} {format} errors!", fg="green") @@ -130,19 +133,21 @@ def cli_message(linter: Linter) -> None: if linter.invalid_asset_format is not None: click.secho() - link_asset_message(linter.invalid_asset_format, "asset", "format") + link_asset_message(linter.invalid_asset_format, "asset", "format", True) if linter.invalid_asset_request is not None: click.secho() - link_asset_message(linter.invalid_asset_request, "asset", "request") + link_asset_message( + linter.invalid_asset_request, "asset", "request", linter.assets_open_urls + ) if linter.invalid_link_format is not None: click.secho() - link_asset_message(linter.invalid_link_format, "link", "format") + link_asset_message(linter.invalid_link_format, "link", "format", True) if linter.invalid_link_request is not None: click.secho() - link_asset_message(linter.invalid_link_request, "link", "request") + link_asset_message(linter.invalid_link_request, "link", "request", True) if linter.error_type != "": click.secho("Validation error type: ", fg="red") From 60f86efef162698a153ea681dc76a7ef87229900 Mon Sep 17 00:00:00 2001 From: Vincent Privat Date: Mon, 13 Jan 2025 16:13:25 +0100 Subject: [PATCH 3/4] Update documentation with latest pdoc --- README.md | 2 +- pdoc/index.html | 7 + pdoc/search.js | 46 + pdoc/stac_check.html | 234 ++ pdoc/stac_check/cli.html | 1191 ++++---- pdoc/stac_check/index.html | 65 - pdoc/stac_check/lint.html | 5225 ++++++++++++++++++++---------------- pdoc/stac_check/logo.html | 265 ++ 8 files changed, 4234 insertions(+), 2801 deletions(-) create mode 100644 pdoc/index.html create mode 100644 pdoc/search.js create mode 100644 pdoc/stac_check.html delete mode 100644 pdoc/stac_check/index.html create mode 100644 pdoc/stac_check/logo.html diff --git a/README.md b/README.md index 59ce8a8..5ff9238 100644 --- a/README.md +++ b/README.md @@ -254,4 +254,4 @@ This object has 4 links --- ### Create local docs in the /docs folder -`$ pdoc --html --output-dir pdoc stac_check --force` +`$ pdoc --output-dir pdoc ./stac_check` diff --git a/pdoc/index.html b/pdoc/index.html new file mode 100644 index 0000000..0f3f728 --- /dev/null +++ b/pdoc/index.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/pdoc/search.js b/pdoc/search.js new file mode 100644 index 0000000..6928745 --- /dev/null +++ b/pdoc/search.js @@ -0,0 +1,46 @@ +window.pdocSearch = (function(){ +/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o

\n"}, "stac_check.cli": {"fullname": "stac_check.cli", "modulename": "stac_check.cli", "kind": "module", "doc": "

\n"}, "stac_check.cli.link_asset_message": {"fullname": "stac_check.cli.link_asset_message", "modulename": "stac_check.cli", "qualname": "link_asset_message", "kind": "function", "doc": "

Prints a list of links or assets and any errors associated with them.

\n\n

Args:\n link_list (list): A list of links or assets.\n type (str): The type of link or asset being processed.\n format (str): The format or request being used.\n healthy_msg (bool): Whether to display \"No TYPE errors!\" or not

\n\n

Returns:\n None.

\n", "signature": "(link_list: list, type: str, format: str, healthy_msg: bool) -> None:", "funcdef": "def"}, "stac_check.cli.recursive_message": {"fullname": "stac_check.cli.recursive_message", "modulename": "stac_check.cli", "qualname": "recursive_message", "kind": "function", "doc": "

Displays messages related to the recursive validation of assets in a collection or catalog.

\n\n

Args:\n linter: An instance of the Linter class.

\n\n

Returns:\n None.

\n", "signature": "(linter: stac_check.lint.Linter) -> None:", "funcdef": "def"}, "stac_check.cli.intro_message": {"fullname": "stac_check.cli.intro_message", "modulename": "stac_check.cli", "qualname": "intro_message", "kind": "function", "doc": "

Prints an introduction message for the stac-check tool.

\n\n

The message includes the stac-check logo, the name of the tool, the version\nof the STAC spec being validated, an update message, and the version of the\nstac-validator being used.

\n\n

Args:\n linter (object): An instance of the Linter class, which is used to\n obtain the version of the STAC spec being validated, the update\n message, and the version of the stac-validator being used.

\n\n

Returns:\n None.

\n", "signature": "(linter: stac_check.lint.Linter) -> None:", "funcdef": "def"}, "stac_check.cli.cli_message": {"fullname": "stac_check.cli.cli_message", "modulename": "stac_check.cli", "qualname": "cli_message", "kind": "function", "doc": "

Prints various messages about the STAC object being validated.

\n\n

Args:\n linter: The Linter object containing information about\n the STAC object to be validated.

\n\n

Returns:\n None

\n", "signature": "(linter: stac_check.lint.Linter) -> None:", "funcdef": "def"}, "stac_check.lint": {"fullname": "stac_check.lint", "modulename": "stac_check.lint", "kind": "module", "doc": "

\n"}, "stac_check.lint.Linter": {"fullname": "stac_check.lint.Linter", "modulename": "stac_check.lint", "qualname": "Linter", "kind": "class", "doc": "

A class for linting STAC JSON files and generating validation messages.

\n\n

Args:\n item (Union[str, dict]): A URL, file name, or dictionary representing a STAC JSON file.\n config_file (Optional[str], optional): A path to a YAML configuration file. Defaults to None.\n assets (bool, optional): A boolean value indicating whether to validate assets. Defaults to False.\n links (bool, optional): A boolean value indicating whether to validate links. Defaults to False.\n recursive (bool, optional): A boolean value indicating whether to perform recursive validation. Defaults to False.\n max_depth (Optional[int], optional): An optional integer indicating the maximum depth to validate recursively. Defaults to None.\n assets_open_urls (bool): Whether to open assets URLs when validating assets. Defaults to True.\n headers (dict): HTTP headers to include in the requests.

\n\n

Attributes:\n data (dict): A dictionary representing the STAC JSON file.\n message (dict): A dictionary containing the validation message for the STAC JSON file.\n config (dict): A dictionary containing the configuration settings.\n asset_type (str): A string representing the asset type, if one is specified.\n version (str): A string representing the version of the STAC standard used in the STAC JSON file.\n validator_version (str): A string representing the version of the STAC validator used to validate the STAC JSON file.\n validate_all (dict): A dictionary containing the validation message for all STAC JSON files found recursively, if recursive validation was performed.\n valid_stac (bool): A boolean value indicating whether the STAC JSON file is valid.\n error_type (str): A string representing the type of error in the STAC JSON file, if one exists.\n error_msg (str): A string representing the error message in the STAC JSON file, if one exists.\n invalid_asset_format (List[str]): A list of URLs with invalid asset formats, if assets were validated.\n invalid_asset_request (List[str]): A list of URLs with invalid asset requests, if assets were validated.\n invalid_link_format (List[str]): A list of URLs with invalid link formats, if links were validated.\n invalid_link_request (List[str]): A list of URLs with invalid link requests, if links were validated.\n schema (List[str]): A list of the STAC JSON file's JSON schema files.\n object_id (str): A string representing the STAC JSON file's ID.\n file_name (str): A string representing the name of the file containing the STAC JSON data.\n best_practices_msg (str): A string representing best practices messages for the STAC JSON file.

\n\n

Methods:\n parse_config(config_file: Optional[str] = None) -> Dict:\n Parses a YAML configuration file and returns a dictionary with the configuration settings.

\n\n
def get_asset_name(self, file: Union[str, Dict] = None) -> str:\n    Returns the name of a file.\n\nload_data(self, file: Union[str, Dict]) -> Dict:\n    Loads a STAC JSON file from a URL or file path and returns a dictionary representation.\n\nvalidate_file(self, file: Union[str, dict]) -> Dict[str, Any]:\n    Validates a STAC JSON file and returns a dictionary with the validation message.\n\nrecursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:\n    Validates a STAC JSON file recursively and returns a dictionary with the validation message.\n\nset_update_message(self) -> str:\n    Sets a message regarding the recommended version of the STAC JSON file standard.\n\ncheck_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:\n    Checks whether the STAC JSON file has links or assets with invalid formats or requests.\n\ncheck_error_type(self) -> str:\n    Checks whether the STAC JSON file has an error type.\n\ncheck_error_message(self) -> str:\n    Checks whether the STAC JSON file has an error message.\n\ndef check_summaries(self) -> bool:\n    Checks whether the STAC JSON file has summaries.\n\ncheck_bloated_links(self, max_links: Optional[int] = 20) -> bool:\n    Checks whether the STAC JSON file has bloated links.\n\ncheck_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:\n    Checks whether the STAC JSON file has bloated metadata.\n\ncheck_datetime_null(self) -> bool:\n    Checks whether the STAC JSON file has a null datetime.\n\ncheck_unlocated(self) -> bool:\n    Checks whether the STAC JSON file has unlocated items.\n\ncheck_geometry_null(self) -> bool:\n    Checks whether the STAC JSON file has a null geometry.\n\ncheck_searchable_identifiers(self) -> bool:\n    Checks whether the STAC JSON file has searchable identifiers.\n\ncheck_percent_encoded(self) -> bool:\n    Checks whether the STAC JSON file has percent-encoded characters.\n\ncheck_thumbnail(self) -> bool:\n    Checks whether the STAC JSON file has a thumbnail.\n\ncheck_links_title_field(self) -> bool:\n    Checks whether the STAC JSON file has a title field in its links.\n\ncheck_links_self(self) -> bool:\n    Checks whether the STAC JSON file has a self link.\n\ncheck_item_id_file_name(self) -> bool:\n    Checks whether the filename of an Item conforms to the STAC specification.\n\ncheck_catalog_file_name(self) -> str:\n    Checks whether the filename of a Catalog or Collection conforms to the STAC specification.\n\ncreate_best_practices_dict(self) -> Dict[str, Any]:\n    Creates a dictionary with best practices recommendations for the STAC JSON file.\n\ncreate_best_practices_msg(self) -> List[str]:\n    Creates a message with best practices recommendations for the STAC JSON file.\n
\n"}, "stac_check.lint.Linter.__init__": {"fullname": "stac_check.lint.Linter.__init__", "modulename": "stac_check.lint", "qualname": "Linter.__init__", "kind": "function", "doc": "

\n", "signature": "(\titem: Union[str, dict],\tconfig_file: Optional[str] = None,\tassets: bool = False,\tlinks: bool = False,\trecursive: bool = False,\tmax_depth: Optional[int] = None,\tassets_open_urls: bool = True,\theaders: dict = <factory>)"}, "stac_check.lint.Linter.item": {"fullname": "stac_check.lint.Linter.item", "modulename": "stac_check.lint", "qualname": "Linter.item", "kind": "variable", "doc": "

\n", "annotation": ": Union[str, dict]"}, "stac_check.lint.Linter.config_file": {"fullname": "stac_check.lint.Linter.config_file", "modulename": "stac_check.lint", "qualname": "Linter.config_file", "kind": "variable", "doc": "

\n", "annotation": ": Optional[str]", "default_value": "None"}, "stac_check.lint.Linter.assets": {"fullname": "stac_check.lint.Linter.assets", "modulename": "stac_check.lint", "qualname": "Linter.assets", "kind": "variable", "doc": "

\n", "annotation": ": bool", "default_value": "False"}, "stac_check.lint.Linter.links": {"fullname": "stac_check.lint.Linter.links", "modulename": "stac_check.lint", "qualname": "Linter.links", "kind": "variable", "doc": "

\n", "annotation": ": bool", "default_value": "False"}, "stac_check.lint.Linter.recursive": {"fullname": "stac_check.lint.Linter.recursive", "modulename": "stac_check.lint", "qualname": "Linter.recursive", "kind": "variable", "doc": "

\n", "annotation": ": bool", "default_value": "False"}, "stac_check.lint.Linter.max_depth": {"fullname": "stac_check.lint.Linter.max_depth", "modulename": "stac_check.lint", "qualname": "Linter.max_depth", "kind": "variable", "doc": "

\n", "annotation": ": Optional[int]", "default_value": "None"}, "stac_check.lint.Linter.assets_open_urls": {"fullname": "stac_check.lint.Linter.assets_open_urls", "modulename": "stac_check.lint", "qualname": "Linter.assets_open_urls", "kind": "variable", "doc": "

\n", "annotation": ": bool", "default_value": "True"}, "stac_check.lint.Linter.headers": {"fullname": "stac_check.lint.Linter.headers", "modulename": "stac_check.lint", "qualname": "Linter.headers", "kind": "variable", "doc": "

\n", "annotation": ": dict"}, "stac_check.lint.Linter.parse_config": {"fullname": "stac_check.lint.Linter.parse_config", "modulename": "stac_check.lint", "qualname": "Linter.parse_config", "kind": "function", "doc": "

Parse the configuration file for STAC checks.

\n\n

The method first looks for a file path specified in the STAC_CHECK_CONFIG\nenvironment variable. If the variable is defined, the method loads the\nYAML configuration file located at that path. Otherwise, it loads the default\nconfiguration file packaged with the stac-check module.

\n\n

If config_file is specified, the method also loads the YAML configuration\nfile located at that path and merges its contents with the default or\nenvironment-based configuration.

\n\n

Args:\n config_file (str): The path to the YAML configuration file.

\n\n

Returns:\n A dictionary containing the parsed configuration values.

\n\n

Raises:\n IOError: If config_file is specified but cannot be read.\n yaml.YAMLError: If any YAML syntax errors occur while parsing the\n configuration file(s).

\n", "signature": "(config_file: Optional[str] = None) -> Dict:", "funcdef": "def"}, "stac_check.lint.Linter.get_asset_name": {"fullname": "stac_check.lint.Linter.get_asset_name", "modulename": "stac_check.lint", "qualname": "Linter.get_asset_name", "kind": "function", "doc": "

Extracts the name of an asset from its file path or from a STAC item asset dictionary.

\n\n

Args:\n file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the\n asset as specified in a STAC item's assets property.

\n\n

Returns:\n A string containing the name of the asset.

\n\n

Raises:\n TypeError: If the input file is not a string or a dictionary.

\n", "signature": "(self, file: Union[str, Dict] = None) -> str:", "funcdef": "def"}, "stac_check.lint.Linter.load_data": {"fullname": "stac_check.lint.Linter.load_data", "modulename": "stac_check.lint", "qualname": "Linter.load_data", "kind": "function", "doc": "

Loads JSON data from a file or URL.

\n\n

Args:\n file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.

\n\n

Returns:\n A dictionary containing the loaded JSON data.

\n\n

Raises:\n TypeError: If the input file is not a string or dictionary.\n ValueError: If file is a string that doesn't represent a valid URL or file path.\n requests.exceptions.RequestException: If there is an error making a request to a URL.\n JSONDecodeError: If the JSON data cannot be decoded.\n FileNotFoundError: If the specified file cannot be found.

\n", "signature": "(self, file: Union[str, Dict]) -> Dict:", "funcdef": "def"}, "stac_check.lint.Linter.validate_file": {"fullname": "stac_check.lint.Linter.validate_file", "modulename": "stac_check.lint", "qualname": "Linter.validate_file", "kind": "function", "doc": "

Validates the given file path or STAC dictionary against the validation schema.

\n\n

Args:\n file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC\n item.

\n\n

Returns:\n A dictionary containing the results of the validation, including the status of the validation and any errors\n encountered.

\n\n

Raises:\n ValueError: If file is not a valid file path or STAC dictionary.

\n", "signature": "(self, file: Union[str, dict]) -> Dict[str, Any]:", "funcdef": "def"}, "stac_check.lint.Linter.recursive_validation": {"fullname": "stac_check.lint.Linter.recursive_validation", "modulename": "stac_check.lint", "qualname": "Linter.recursive_validation", "kind": "function", "doc": "

Recursively validate a STAC item or catalog file and its child items.

\n\n

Args:\n file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a\n dictionary representing the STAC item or catalog.

\n\n

Returns:\n A string containing the validation message.

\n\n

Raises:\n TypeError: If the input file is not a string or a dictionary.

\n", "signature": "(self, file: Union[str, Dict[str, Any]]) -> str:", "funcdef": "def"}, "stac_check.lint.Linter.set_update_message": {"fullname": "stac_check.lint.Linter.set_update_message", "modulename": "stac_check.lint", "qualname": "Linter.set_update_message", "kind": "function", "doc": "

Returns a message for users to update their STAC version.

\n\n

Returns:\n A string containing a message for users to update their STAC version.

\n", "signature": "(self) -> str:", "funcdef": "def"}, "stac_check.lint.Linter.check_links_assets": {"fullname": "stac_check.lint.Linter.check_links_assets", "modulename": "stac_check.lint", "qualname": "Linter.check_links_assets", "kind": "function", "doc": "

Checks the links and assets in the STAC catalog and returns a list of invalid links of a specified type and format.

\n\n

Args:\n num_links (int): The maximum number of invalid links to return.\n url_type (str): The type of URL to check, which can be either 'self' or 'external'.\n format_type (str): The format of the URL to check, which can be either 'html' or 'json'.

\n\n

Returns:\n A list of invalid links of the specified type and format. If there are no invalid links, an empty list is returned.

\n", "signature": "(self, num_links: int, url_type: str, format_type: str) -> List[str]:", "funcdef": "def"}, "stac_check.lint.Linter.check_error_type": {"fullname": "stac_check.lint.Linter.check_error_type", "modulename": "stac_check.lint", "qualname": "Linter.check_error_type", "kind": "function", "doc": "

Returns the error type of a STAC validation if it exists in the validation message,\nand an empty string otherwise.

\n\n

Returns:\n str: A string containing the error type of a STAC validation if it exists in the validation message, and an\n empty string otherwise.

\n", "signature": "(self) -> str:", "funcdef": "def"}, "stac_check.lint.Linter.check_error_message": {"fullname": "stac_check.lint.Linter.check_error_message", "modulename": "stac_check.lint", "qualname": "Linter.check_error_message", "kind": "function", "doc": "

Checks whether the message attribute contains an error_message field.

\n\n

Returns:\n A string containing the value of the error_message field, or an empty string if the field is not present.

\n", "signature": "(self) -> str:", "funcdef": "def"}, "stac_check.lint.Linter.check_summaries": {"fullname": "stac_check.lint.Linter.check_summaries", "modulename": "stac_check.lint", "qualname": "Linter.check_summaries", "kind": "function", "doc": "

Check if a Collection asset has a \"summaries\" property.

\n\n

Returns:\n A boolean indicating whether the Collection asset has a \"summaries\" property.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_bloated_links": {"fullname": "stac_check.lint.Linter.check_bloated_links", "modulename": "stac_check.lint", "qualname": "Linter.check_bloated_links", "kind": "function", "doc": "

Checks if the number of links in the STAC data exceeds a certain maximum.

\n\n

Args:\n max_links (Optional[int]): The maximum number of links that the STAC data is allowed to have. Default is 20.

\n\n

Returns:\n bool: A boolean indicating if the number of links in the STAC data exceeds the specified maximum.

\n", "signature": "(self, max_links: Optional[int] = 20) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_bloated_metadata": {"fullname": "stac_check.lint.Linter.check_bloated_metadata", "modulename": "stac_check.lint", "qualname": "Linter.check_bloated_metadata", "kind": "function", "doc": "

Checks whether a STAC item's metadata contains too many properties.

\n\n

Args:\n max_properties (int, optional): The maximum number of properties that the metadata can contain before it is\n considered too bloated. Defaults to 20.

\n\n

Returns:\n bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by\n max_properties, False otherwise.

\n", "signature": "(self, max_properties: Optional[int] = 20) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_datetime_null": {"fullname": "stac_check.lint.Linter.check_datetime_null", "modulename": "stac_check.lint", "qualname": "Linter.check_datetime_null", "kind": "function", "doc": "

Checks if the STAC item has a null datetime property.

\n\n

Returns:\n bool: A boolean indicating whether the datetime property is null (True) or not (False).

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_unlocated": {"fullname": "stac_check.lint.Linter.check_unlocated", "modulename": "stac_check.lint", "qualname": "Linter.check_unlocated", "kind": "function", "doc": "

Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.

\n\n

Returns:\n bool: True if the STAC item is unlocated, False otherwise.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_geometry_null": {"fullname": "stac_check.lint.Linter.check_geometry_null", "modulename": "stac_check.lint", "qualname": "Linter.check_geometry_null", "kind": "function", "doc": "

Checks if a STAC item has a null geometry property.

\n\n

Returns:\n bool: A boolean indicating whether the geometry property is null (True) or not (False).

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_searchable_identifiers": {"fullname": "stac_check.lint.Linter.check_searchable_identifiers", "modulename": "stac_check.lint", "qualname": "Linter.check_searchable_identifiers", "kind": "function", "doc": "

Checks if the identifiers of a STAC item are searchable, i.e.,\nthey only contain lowercase letters, numbers, hyphens, and underscores.

\n\n

Returns:\n bool: True if the identifiers are searchable, False otherwise.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_percent_encoded": {"fullname": "stac_check.lint.Linter.check_percent_encoded", "modulename": "stac_check.lint", "qualname": "Linter.check_percent_encoded", "kind": "function", "doc": "

Checks if the identifiers of a STAC item are percent-encoded, i.e.,\nthey only contain lowercase letters, numbers, hyphens, and underscores.

\n\n

Returns:\n bool: True if the identifiers are percent-encoded, False otherwise.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_thumbnail": {"fullname": "stac_check.lint.Linter.check_thumbnail", "modulename": "stac_check.lint", "qualname": "Linter.check_thumbnail", "kind": "function", "doc": "

Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format.

\n\n

Returns:\n bool: True if the thumbnail is valid, False otherwise.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_links_title_field": {"fullname": "stac_check.lint.Linter.check_links_title_field", "modulename": "stac_check.lint", "qualname": "Linter.check_links_title_field", "kind": "function", "doc": "

Checks if all links in a STAC collection or catalog have a 'title' field.\nThe 'title' field is not required for the 'self' link.

\n\n

Returns:\n bool: True if all links have a 'title' field, False otherwise.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_links_self": {"fullname": "stac_check.lint.Linter.check_links_self", "modulename": "stac_check.lint", "qualname": "Linter.check_links_self", "kind": "function", "doc": "

Checks whether the \"self\" link is present in the STAC collection or catalog or absent in STAC item.

\n\n

Returns:\n bool: True if the \"self\" link is present in STAC collection or catalog or absent in STAC item, False otherwise.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_item_id_file_name": {"fullname": "stac_check.lint.Linter.check_item_id_file_name", "modulename": "stac_check.lint", "qualname": "Linter.check_item_id_file_name", "kind": "function", "doc": "

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.check_catalog_file_name": {"fullname": "stac_check.lint.Linter.check_catalog_file_name", "modulename": "stac_check.lint", "qualname": "Linter.check_catalog_file_name", "kind": "function", "doc": "

Checks whether the filename of a Catalog or Collection conforms to the STAC specification.

\n\n

Returns:\n bool: True if the filename is valid, False otherwise.

\n", "signature": "(self) -> bool:", "funcdef": "def"}, "stac_check.lint.Linter.create_best_practices_dict": {"fullname": "stac_check.lint.Linter.create_best_practices_dict", "modulename": "stac_check.lint", "qualname": "Linter.create_best_practices_dict", "kind": "function", "doc": "

Creates a dictionary of best practices violations for the current STAC object. The violations are determined\nby a set of configurable linting rules specified in the config file.

\n\n

Returns:\n A dictionary of best practices violations for the current STAC object. The keys in the dictionary correspond\n to the linting rules that were violated, and the values are lists of strings containing error messages and\n recommendations for how to fix the violations.

\n", "signature": "(self) -> Dict:", "funcdef": "def"}, "stac_check.lint.Linter.create_best_practices_msg": {"fullname": "stac_check.lint.Linter.create_best_practices_msg", "modulename": "stac_check.lint", "qualname": "Linter.create_best_practices_msg", "kind": "function", "doc": "

Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method.

\n\n

Returns:\n A list of strings, where each string contains a best practice message. Each message starts with the\n 'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented\n with four spaces, and there is an empty string between each message for readability.

\n", "signature": "(self) -> List[str]:", "funcdef": "def"}, "stac_check.logo": {"fullname": "stac_check.logo", "modulename": "stac_check.logo", "kind": "module", "doc": "

\n"}, "stac_check.logo.logo": {"fullname": "stac_check.logo.logo", "modulename": "stac_check.logo", "qualname": "logo", "kind": "variable", "doc": "

\n", "default_value": "'\\n ____ ____ __ ___ ___ _ _ ____ ___ __ _ \\n/ ___)(_ _)/ _\\\\ / __)___ / __)/ )( \\\\( __)/ __)( / )\\n\\\\___ \\\\ )( / \\\\( (__(___)( (__ ) __ ( ) _)( (__ ) ( \\n(____/ (__)\\\\_/\\\\_/ \\\\___) \\\\___)\\\\_)(_/(____)\\\\___)(__\\\\_)\\n '"}}, "docInfo": {"stac_check": {"qualname": 0, "fullname": 2, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "stac_check.cli": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "stac_check.cli.link_asset_message": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 51, "bases": 0, "doc": 66}, "stac_check.cli.recursive_message": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 30, "bases": 0, "doc": 33}, "stac_check.cli.intro_message": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 30, "bases": 0, "doc": 90}, "stac_check.cli.cli_message": {"qualname": 2, "fullname": 5, "annotation": 0, "default_value": 0, "signature": 30, "bases": 0, "doc": 35}, "stac_check.lint": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 885}, "stac_check.lint.Linter.__init__": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 177, "bases": 0, "doc": 3}, "stac_check.lint.Linter.item": {"qualname": 2, "fullname": 5, "annotation": 3, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.config_file": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.assets": {"qualname": 2, "fullname": 5, "annotation": 2, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.links": {"qualname": 2, "fullname": 5, "annotation": 2, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.recursive": {"qualname": 2, "fullname": 5, "annotation": 2, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.max_depth": {"qualname": 3, "fullname": 6, "annotation": 2, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.assets_open_urls": {"qualname": 4, "fullname": 7, "annotation": 2, "default_value": 1, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.headers": {"qualname": 2, "fullname": 5, "annotation": 2, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "stac_check.lint.Linter.parse_config": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 33, "bases": 0, "doc": 151}, "stac_check.lint.Linter.get_asset_name": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 43, "bases": 0, "doc": 85}, "stac_check.lint.Linter.load_data": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 36, "bases": 0, "doc": 111}, "stac_check.lint.Linter.validate_file": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 48, "bases": 0, "doc": 80}, "stac_check.lint.Linter.recursive_validation": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 46, "bases": 0, "doc": 73}, "stac_check.lint.Linter.set_update_message": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 29}, "stac_check.lint.Linter.check_links_assets": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 53, "bases": 0, "doc": 102}, "stac_check.lint.Linter.check_error_type": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 50}, "stac_check.lint.Linter.check_error_message": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 43}, "stac_check.lint.Linter.check_summaries": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 27}, "stac_check.lint.Linter.check_bloated_links": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 38, "bases": 0, "doc": 62}, "stac_check.lint.Linter.check_bloated_metadata": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 38, "bases": 0, "doc": 70}, "stac_check.lint.Linter.check_datetime_null": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 31}, "stac_check.lint.Linter.check_unlocated": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 34}, "stac_check.lint.Linter.check_geometry_null": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 31}, "stac_check.lint.Linter.check_searchable_identifiers": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 37}, "stac_check.lint.Linter.check_percent_encoded": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 39}, "stac_check.lint.Linter.check_thumbnail": {"qualname": 3, "fullname": 6, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 33}, "stac_check.lint.Linter.check_links_title_field": {"qualname": 5, "fullname": 8, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 42}, "stac_check.lint.Linter.check_links_self": {"qualname": 4, "fullname": 7, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 45}, "stac_check.lint.Linter.check_item_id_file_name": {"qualname": 6, "fullname": 9, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 3}, "stac_check.lint.Linter.check_catalog_file_name": {"qualname": 5, "fullname": 8, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 30}, "stac_check.lint.Linter.create_best_practices_dict": {"qualname": 5, "fullname": 8, "annotation": 0, "default_value": 0, "signature": 14, "bases": 0, "doc": 77}, "stac_check.lint.Linter.create_best_practices_msg": {"qualname": 5, "fullname": 8, "annotation": 0, "default_value": 0, "signature": 20, "bases": 0, "doc": 72}, "stac_check.logo": {"qualname": 0, "fullname": 3, "annotation": 0, "default_value": 0, "signature": 0, "bases": 0, "doc": 3}, "stac_check.logo.logo": {"qualname": 1, "fullname": 4, "annotation": 0, "default_value": 30, "signature": 0, "bases": 0, "doc": 3}}, "length": 43, "save": true}, "index": {"qualname": {"root": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}}, "df": 5}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.max_depth": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.headers": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 34}}}}}, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}, "g": {"docs": {}, "df": 0, "o": {"docs": {"stac_check.logo.logo": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}}, "df": 2, "s": {"docs": {"stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 3}}}}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}}, "df": 6}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "x": {"docs": {"stac_check.lint.Linter.max_depth": {"tf": 1}}, "df": 1}}, "s": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 3}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {"stac_check.cli.intro_message": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}}, "df": 2}}}, "d": {"docs": {"stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}}, "df": 1}}}}}}}}}}}, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {"stac_check.cli.cli_message": {"tf": 1}}, "df": 1}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 2}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 16}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 4}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_links_title_field": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.lint.Linter.max_depth": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_datetime_null": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.assets_open_urls": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.assets_open_urls": {"tf": 1}}, "df": 1}}}, "p": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.set_update_message": {"tf": 1}}, "df": 1}}}}}, "n": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_unlocated": {"tf": 1}}, "df": 1}}}}}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.headers": {"tf": 1}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}}, "df": 1}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.check_geometry_null": {"tf": 1}}, "df": 1}}}}}}}}, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 3}}}, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}}, "df": 2}}}}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 1}}}}}}}}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.set_update_message": {"tf": 1}}, "df": 1}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}}, "df": 1}}}}}}}}, "l": {"docs": {}, "df": 0, "f": {"docs": {"stac_check.lint.Linter.check_links_self": {"tf": 1}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_summaries": {"tf": 1}}, "df": 1}}}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}}, "df": 2}}}}, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 1}}}}}}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_error_type": {"tf": 1}}, "df": 1}}}, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.check_thumbnail": {"tf": 1}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_links_title_field": {"tf": 1}}, "df": 1}}}}}, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 2}}}}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}}, "fullname": {"root": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {"stac_check": {"tf": 1}, "stac_check.cli": {"tf": 1}, "stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.max_depth": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.headers": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}, "stac_check.logo": {"tf": 1}, "stac_check.logo.logo": {"tf": 1}}, "df": 43}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.set_update_message": {"tf": 1}}, "df": 1}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}}, "df": 1}}}}}}}}, "l": {"docs": {}, "df": 0, "f": {"docs": {"stac_check.lint.Linter.check_links_self": {"tf": 1}}, "df": 1}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_summaries": {"tf": 1}}, "df": 1}}}}}}}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"stac_check": {"tf": 1}, "stac_check.cli": {"tf": 1}, "stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.max_depth": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.headers": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_summaries": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}, "stac_check.logo": {"tf": 1}, "stac_check.logo.logo": {"tf": 1}}, "df": 43}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {"stac_check.cli": {"tf": 1}, "stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1.4142135623730951}}, "df": 5}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 2}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}}, "df": 5}}, "t": {"docs": {"stac_check.lint": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.max_depth": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.headers": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 35, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.max_depth": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.headers": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 34}}}}}, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}, "g": {"docs": {}, "df": 0, "o": {"docs": {"stac_check.logo": {"tf": 1}, "stac_check.logo.logo": {"tf": 1.4142135623730951}}, "df": 2}}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}}, "df": 2, "s": {"docs": {"stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 3}}}}}}, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}}, "df": 6}}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "x": {"docs": {"stac_check.lint.Linter.max_depth": {"tf": 1}}, "df": 1}}, "s": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 3}}}}}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {"stac_check.cli.intro_message": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}}, "df": 2}}}, "d": {"docs": {"stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}}, "df": 1}}}}}}}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 4}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_links_title_field": {"tf": 1}}, "df": 1}}}}}, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.lint.Linter.max_depth": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_datetime_null": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.assets_open_urls": {"tf": 1}}, "df": 1}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.assets_open_urls": {"tf": 1}}, "df": 1}}}, "p": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.set_update_message": {"tf": 1}}, "df": 1}}}}}, "n": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_unlocated": {"tf": 1}}, "df": 1}}}}}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.headers": {"tf": 1}}, "df": 1}}}}}}}, "p": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 1}}}}}}, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}}, "df": 1}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.check_geometry_null": {"tf": 1}}, "df": 1}}}}}}}}, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 3}}}, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}}, "df": 2}}}}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 1}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 1}}}}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}}, "df": 2}}}}, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 1}}}}}}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_error_type": {"tf": 1}}, "df": 1}}}, "h": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.check_thumbnail": {"tf": 1}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_links_title_field": {"tf": 1}}, "df": 1}}}}}, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 2}}}}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}}, "annotation": {"root": {"docs": {"stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.max_depth": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}, "stac_check.lint.Linter.headers": {"tf": 1}}, "df": 8, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.item": {"tf": 1}}, "df": 1}}}}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.item": {"tf": 1}, "stac_check.lint.Linter.headers": {"tf": 1}}, "df": 2}}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.config_file": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.max_depth": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1}}, "df": 4}}}}}}, "default_value": {"root": {"docs": {"stac_check.logo.logo": {"tf": 4.795831523312719}}, "df": 1, "n": {"docs": {"stac_check.logo.logo": {"tf": 2.23606797749979}}, "df": 1, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.config_file": {"tf": 1}, "stac_check.lint.Linter.max_depth": {"tf": 1}}, "df": 2}}}}, "f": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.assets": {"tf": 1}, "stac_check.lint.Linter.links": {"tf": 1}, "stac_check.lint.Linter.recursive": {"tf": 1}}, "df": 3}}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.assets_open_urls": {"tf": 1}}, "df": 1}}}}, "x": {"2": {"7": {"docs": {"stac_check.logo.logo": {"tf": 1.4142135623730951}}, "df": 1}, "docs": {}, "df": 0}, "docs": {}, "df": 0}}}, "signature": {"root": {"2": {"0": {"docs": {"stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 2}, "docs": {}, "df": 0}, "docs": {"stac_check.cli.link_asset_message": {"tf": 6.324555320336759}, "stac_check.cli.recursive_message": {"tf": 4.898979485566356}, "stac_check.cli.intro_message": {"tf": 4.898979485566356}, "stac_check.cli.cli_message": {"tf": 4.898979485566356}, "stac_check.lint.Linter.__init__": {"tf": 12}, "stac_check.lint.Linter.parse_config": {"tf": 5.196152422706632}, "stac_check.lint.Linter.get_asset_name": {"tf": 6}, "stac_check.lint.Linter.load_data": {"tf": 5.477225575051661}, "stac_check.lint.Linter.validate_file": {"tf": 6.324555320336759}, "stac_check.lint.Linter.recursive_validation": {"tf": 6.164414002968976}, "stac_check.lint.Linter.set_update_message": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_links_assets": {"tf": 6.4031242374328485}, "stac_check.lint.Linter.check_error_type": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_error_message": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_summaries": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_bloated_links": {"tf": 5.5677643628300215}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 5.5677643628300215}, "stac_check.lint.Linter.check_datetime_null": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_unlocated": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_geometry_null": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_thumbnail": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_links_title_field": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_links_self": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 4.123105625617661}}, "df": 29, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "k": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}}, "df": 3}}, "t": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}}, "df": 3, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.cli.recursive_message": {"tf": 1.4142135623730951}, "stac_check.cli.intro_message": {"tf": 1.4142135623730951}, "stac_check.cli.cli_message": {"tf": 1.4142135623730951}}, "df": 3}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 3}}}, "t": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}, "t": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}}, "df": 2}}}, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.__init__": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.recursive_validation": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 12}, "a": {"docs": {}, "df": 0, "c": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}}, "df": 3}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "f": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 23}}}}, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 2}}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 6}}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1.7320508075688772}}, "df": 1}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}}}}}, "m": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "x": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 3}}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter.__init__": {"tf": 2}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 15}}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter.__init__": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}}, "df": 7}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 1}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}}, "df": 3}}}}, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 2}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 4}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 5}}}}, "r": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 7}}}, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}}}, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 4}}}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "n": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 2}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}}}}}}}}, "g": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.__init__": {"tf": 1}}, "df": 1}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "bases": {"root": {"docs": {}, "df": 0}}, "doc": {"root": {"2": {"0": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 3}, "docs": {}, "df": 0}, "docs": {"stac_check": {"tf": 1.7320508075688772}, "stac_check.cli": {"tf": 1.7320508075688772}, "stac_check.cli.link_asset_message": {"tf": 3.4641016151377544}, "stac_check.cli.recursive_message": {"tf": 3}, "stac_check.cli.intro_message": {"tf": 3.605551275463989}, "stac_check.cli.cli_message": {"tf": 3.1622776601683795}, "stac_check.lint": {"tf": 1.7320508075688772}, "stac_check.lint.Linter": {"tf": 6.6332495807108}, "stac_check.lint.Linter.__init__": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.item": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.config_file": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.assets": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.links": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.recursive": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.max_depth": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.assets_open_urls": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.headers": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.parse_config": {"tf": 5.196152422706632}, "stac_check.lint.Linter.get_asset_name": {"tf": 4.123105625617661}, "stac_check.lint.Linter.load_data": {"tf": 4.123105625617661}, "stac_check.lint.Linter.validate_file": {"tf": 3.872983346207417}, "stac_check.lint.Linter.recursive_validation": {"tf": 3.872983346207417}, "stac_check.lint.Linter.set_update_message": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_links_assets": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_error_type": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_error_message": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_summaries": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_bloated_links": {"tf": 3.1622776601683795}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.check_datetime_null": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_unlocated": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_geometry_null": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_thumbnail": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_links_title_field": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_links_self": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_item_id_file_name": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 2.449489742783178}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 2.449489742783178}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 2.449489742783178}, "stac_check.logo": {"tf": 1.7320508075688772}, "stac_check.logo.logo": {"tf": 1.7320508075688772}}, "df": 43, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}}, "df": 3}}}}, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1}}}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 2.449489742783178}}, "df": 2}}}, "y": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1.4142135623730951}}, "df": 4}}}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter": {"tf": 2.449489742783178}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.7320508075688772}}, "df": 3}}}}}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}}, "df": 2}}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 2}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.load_data": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 6}}, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 2, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}, "d": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}, "c": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}}}}, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}, "a": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 6.708203932499369}, "stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.get_asset_name": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.load_data": {"tf": 3.1622776601683795}, "stac_check.lint.Linter.validate_file": {"tf": 2}, "stac_check.lint.Linter.recursive_validation": {"tf": 2.449489742783178}, "stac_check.lint.Linter.set_update_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_error_type": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 2}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 2}}, "df": 25, "s": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}}, "df": 1, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.get_asset_name": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_summaries": {"tf": 1.4142135623730951}}, "df": 4, "s": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 3}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 5}}}, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1}}}}}}}}}, "n": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 9, "d": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 2}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.4142135623730951}}, "df": 12}, "y": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 5}}, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 13}}, "e": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}}, "df": 4}}, "b": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.cli_message": {"tf": 1.4142135623730951}}, "df": 1}}}, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}}, "df": 1, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_error_message": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}}}}}}}, "l": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.4142135623730951}}, "df": 2, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_bloated_links": {"tf": 1}}, "df": 1}}}}}, "s": {"docs": {}, "df": 0, "o": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 1}}}}}}}, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 2}, "stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.4142135623730951}}, "df": 4, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 2.6457513110645907}}, "df": 1}}}}, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}, "n": {"docs": {}, "df": 0, "k": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}}, "df": 4, "s": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 3.605551275463989}, "stac_check.lint.Linter.check_links_assets": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_bloated_links": {"tf": 2}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.4142135623730951}}, "df": 5}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.cli.recursive_message": {"tf": 1.4142135623730951}, "stac_check.cli.intro_message": {"tf": 1.4142135623730951}, "stac_check.cli.cli_message": {"tf": 1.4142135623730951}}, "df": 3}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}}, "df": 2}}}}}}, "o": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "o": {"docs": {"stac_check.cli.intro_message": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 3}, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}, "o": {"docs": {}, "df": 0, "k": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 2}}}}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 2}}}}}}}, "o": {"docs": {}, "df": 0, "f": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.7320508075688772}, "stac_check.cli.recursive_message": {"tf": 1.4142135623730951}, "stac_check.cli.intro_message": {"tf": 2.449489742783178}, "stac_check.lint.Linter": {"tf": 3.605551275463989}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_assets": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 2}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.7320508075688772}}, "df": 17}, "r": {"docs": {"stac_check.cli.link_asset_message": {"tf": 2.23606797749979}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.load_data": {"tf": 2}, "stac_check.lint.Linter.validate_file": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.recursive_validation": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 2}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 15}, "b": {"docs": {}, "df": 0, "j": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}}, "df": 4}}}}, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.cli.intro_message": {"tf": 1}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter": {"tf": 2.449489742783178}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 3, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}}, "df": 2}}}}}}}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 1}}}, "n": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}}, "df": 1}, "l": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 2}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 10}}}}}}}}, "c": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {"stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}}, "df": 4, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 2.8284271247461903}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 5, "s": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 3}}}}}, "x": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}}, "df": 2}}}}, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 1}}}}}}, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}}}, "e": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_bloated_links": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 2}}}}}}, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1.4142135623730951}}, "df": 2}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 1}}}}}}}}}, "v": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "m": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 4}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 2}}, "df": 1}}}}, "w": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 3.1622776601683795}, "stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.4142135623730951}}, "df": 4}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 4.58257569495584}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 9}}}}, "n": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.cli.intro_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}}, "df": 2}}, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 2}}}}, "t": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1, "h": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.cli.recursive_message": {"tf": 1.4142135623730951}, "stac_check.cli.intro_message": {"tf": 3.872983346207417}, "stac_check.cli.cli_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter": {"tf": 7.14142842854285}, "stac_check.lint.Linter.parse_config": {"tf": 3.872983346207417}, "stac_check.lint.Linter.get_asset_name": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.load_data": {"tf": 2.449489742783178}, "stac_check.lint.Linter.validate_file": {"tf": 3}, "stac_check.lint.Linter.recursive_validation": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_links_assets": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.check_error_type": {"tf": 2}, "stac_check.lint.Linter.check_error_message": {"tf": 2}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_self": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 3}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.7320508075688772}}, "df": 27, "m": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1}, "r": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 3}}, "i": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}}, "df": 1}}, "y": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 2}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 5}}}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter": {"tf": 2.8284271247461903}, "stac_check.lint.Linter.check_links_assets": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}}, "df": 4, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 3}}}}}}}}, "o": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 4}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}}, "df": 16, "o": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1.4142135623730951}}, "df": 1, "l": {"docs": {"stac_check.cli.intro_message": {"tf": 1.4142135623730951}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 11}}}, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.7320508075688772}}, "df": 2}}}}}, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 4, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 4}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_type": {"tf": 1}}, "df": 5, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 2.8284271247461903}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.load_data": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_error_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.7320508075688772}}, "df": 9, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {"stac_check.cli.intro_message": {"tf": 2.449489742783178}, "stac_check.cli.cli_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 6.244997998398398}, "stac_check.lint.Linter.parse_config": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 2}, "stac_check.lint.Linter.recursive_validation": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 2}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 23}, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 1}}}, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {"stac_check.cli.intro_message": {"tf": 1.4142135623730951}}, "df": 1, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 8}}, "c": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 2}}}}}}}}}}}, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}}}, "e": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 2, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}, "l": {"docs": {}, "df": 0, "f": {"docs": {"stac_check.lint.Linter": {"tf": 5}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}}, "df": 4}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}}}, "c": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 2}}}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_summaries": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}}, "y": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "x": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}}, "b": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}}, "df": 4, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.cli.intro_message": {"tf": 2}, "stac_check.cli.cli_message": {"tf": 1}}, "df": 3}}}, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter": {"tf": 2.449489742783178}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 2}}, "df": 3}}, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 1}}}}, "t": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}}}}, "o": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 4.123105625617661}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 13, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}}, "df": 5}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.check_unlocated": {"tf": 1}}, "df": 1}}}}}}, "x": {"docs": {"stac_check.lint.Linter.check_unlocated": {"tf": 1}}, "df": 1}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 2}}}}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1, "d": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}, "u": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}}, "df": 2}}, "y": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 3}}, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.cli.intro_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2.449489742783178}, "stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 7, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_links_assets": {"tf": 2}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}}, "df": 4, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 2}}, "r": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "w": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 6.855654600401044}, "stac_check.lint.Linter.parse_config": {"tf": 3.1622776601683795}, "stac_check.lint.Linter.get_asset_name": {"tf": 2}, "stac_check.lint.Linter.load_data": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.validate_file": {"tf": 2.449489742783178}, "stac_check.lint.Linter.recursive_validation": {"tf": 2}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 7, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}}, "df": 1}, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1.4142135623730951}}, "df": 2}}}, "o": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}, "e": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.7320508075688772}}, "df": 3}}}, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}, "x": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 11}}}}, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 3}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "q": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 3, "s": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 2}, "e": {"docs": {}, "df": 0, "x": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "i": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_links_title_field": {"tf": 1}}, "df": 1}}}}}}, "t": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 28}, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 1}}}}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}}, "df": 1}}}}}, "c": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2}}, "df": 2, "l": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 2}}}}}}}}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 2}}}}}}}}}}}}}, "p": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 3.1622776601683795}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.recursive_validation": {"tf": 1.4142135623730951}}, "df": 5}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}}}}}}}}}}, "g": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}}}}}, "a": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}}}}}}}, "s": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2}}}}}}, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 5}}}}}, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}}, "df": 1}}}}}, "u": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 3}, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}}, "df": 1}}}}, "p": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.intro_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}}, "df": 3}}}}}, "n": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 5}}}}}}}, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 2}}}}}}}}}}, "r": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.load_data": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.7320508075688772}}, "df": 3, "s": {"docs": {"stac_check.lint.Linter": {"tf": 2.449489742783178}}, "df": 1}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1}}}}, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 1}}}}}}, "t": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "p": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}, "m": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 3.7416573867739413}, "stac_check.lint.Linter.check_summaries": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}}, "df": 6}, "v": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.4142135623730951}}, "df": 2}}}, "y": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 2}}}}}}, "o": {"docs": {}, "df": 0, "w": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}, "m": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1.7320508075688772}}, "df": 2}}, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.intro_message": {"tf": 2}, "stac_check.lint.Linter": {"tf": 3.3166247903554}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 2}}, "df": 7, "s": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 5}}}}}}, "t": {"docs": {}, "df": 0, "h": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}}, "a": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1.7320508075688772}}, "df": 2}}}}}}, "r": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}, "a": {"docs": {}, "df": 0, "x": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1.4142135623730951}}, "df": 3, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1.4142135623730951}}, "df": 4}}}}}, "k": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}, "n": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 1}}}, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}}, "df": 1}}}}}}, "c": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter": {"tf": 3.4641016151377544}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 5, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter": {"tf": 3.1622776601683795}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.load_data": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.validate_file": {"tf": 2}, "stac_check.lint.Linter.recursive_validation": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.7320508075688772}}, "df": 7}}}}}}, "[": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 2}}}}}}}, "e": {"docs": {}, "df": 0, "f": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 1, "a": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}}, "df": 2, "s": {"docs": {"stac_check.lint.Linter": {"tf": 2.449489742783178}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 2}}}}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}, "p": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "h": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 1}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}}, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}}}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.load_data": {"tf": 2}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.7320508075688772}}, "df": 3}, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1.4142135623730951}}, "df": 2}}}}}}}, "o": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}}, "n": {"docs": {}, "df": 0, "o": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}}, "df": 3, "t": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}}, "df": 9}, "n": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.link_asset_message": {"tf": 1}, "stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2}}, "df": 5}}}, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.intro_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2.6457513110645907}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}}, "df": 3}}}, "u": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 2, "b": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1.7320508075688772}}, "df": 3, "s": {"docs": {"stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 2}}}}}, "l": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1.4142135623730951}}, "df": 3}}}}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 5, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2.8284271247461903}, "stac_check.lint.Linter.validate_file": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 2}}, "df": 5}}, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}, "e": {"docs": {"stac_check.lint.Linter": {"tf": 2.449489742783178}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 2, "d": {"docs": {"stac_check.cli.intro_message": {"tf": 1.4142135623730951}, "stac_check.cli.cli_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 2}}, "df": 3}, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 2}}, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.cli.intro_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 1.4142135623730951}}, "df": 2}}}}}}, "u": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.check_error_message": {"tf": 1}}, "df": 2, "s": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 2}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 2}}}}}}}}, "r": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.cli.cli_message": {"tf": 1}}, "df": 1}}}, "a": {"docs": {}, "df": 0, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.cli.intro_message": {"tf": 2}, "stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.set_update_message": {"tf": 1.4142135623730951}}, "df": 3}}}}}}, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 2}}, "df": 1}}}}, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}}}}}}, "i": {"docs": {"stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}}, "df": 4, "n": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 2}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}}, "df": 11, "s": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}}, "df": 2}}}}}}, "t": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 3, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.cli.intro_message": {"tf": 1}}, "df": 1}}}}}}}}}, "e": {"docs": {}, "df": 0, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}}}, "c": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1, "s": {"docs": {"stac_check.cli.intro_message": {"tf": 1}}, "df": 1}}, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 1}}}}}}}, "f": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.cli.cli_message": {"tf": 1}}, "df": 1}}}}}}}}}, "d": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}}, "df": 5}}}}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}}}}, "v": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter": {"tf": 3}, "stac_check.lint.Linter.check_links_assets": {"tf": 2}}, "df": 2}}}}}, "p": {"docs": {}, "df": 0, "u": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 3}}}}, "s": {"docs": {"stac_check.cli.intro_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1.7320508075688772}}, "df": 19}, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}}, "df": 4, "e": {"docs": {}, "df": 0, "m": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.get_asset_name": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}}, "df": 12, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 2}}}, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 4}}, "f": {"docs": {"stac_check.lint.Linter": {"tf": 2.8284271247461903}, "stac_check.lint.Linter.parse_config": {"tf": 2}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 2.23606797749979}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 21}, "d": {"docs": {"stac_check.lint.Linter": {"tf": 1.7320508075688772}}, "df": 1, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1.4142135623730951}}, "df": 3}}}}}}}}}}, "o": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}}}, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1}, "stac_check.lint.Linter.check_summaries": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 6}}}}}}}}, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}}, "df": 3, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.cli.cli_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.get_asset_name": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.validate_file": {"tf": 1}, "stac_check.lint.Linter.recursive_validation": {"tf": 1}, "stac_check.lint.Linter.set_update_message": {"tf": 1}, "stac_check.lint.Linter.check_error_type": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 11}}}, "s": {"docs": {"stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 3}}}}, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}, "f": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.parse_config": {"tf": 2}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 3, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter": {"tf": 2}, "stac_check.lint.Linter.parse_config": {"tf": 2.8284271247461903}}, "df": 2}}}}, "b": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}}}}}}, "o": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 2}}}}}, "s": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 1}}}}}}}}, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "p": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}}}}}}}, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.recursive_validation": {"tf": 1.7320508075688772}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 7}}}}}, "n": {"docs": {"stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}}, "df": 2, "n": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.load_data": {"tf": 1.4142135623730951}}, "df": 2}}}}}, "l": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.cli.recursive_message": {"tf": 1}, "stac_check.cli.intro_message": {"tf": 1}, "stac_check.lint.Linter": {"tf": 1}}, "df": 3}}}}, "h": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "k": {"docs": {"stac_check.cli.intro_message": {"tf": 1.4142135623730951}, "stac_check.lint.Linter": {"tf": 4}, "stac_check.lint.Linter.parse_config": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_links_assets": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_summaries": {"tf": 1}}, "df": 5, "s": {"docs": {"stac_check.lint.Linter": {"tf": 4}, "stac_check.lint.Linter.parse_config": {"tf": 1}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}, "stac_check.lint.Linter.check_error_message": {"tf": 1}, "stac_check.lint.Linter.check_bloated_links": {"tf": 1}, "stac_check.lint.Linter.check_bloated_metadata": {"tf": 1}, "stac_check.lint.Linter.check_datetime_null": {"tf": 1}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1}, "stac_check.lint.Linter.check_searchable_identifiers": {"tf": 1}, "stac_check.lint.Linter.check_percent_encoded": {"tf": 1}, "stac_check.lint.Linter.check_thumbnail": {"tf": 1}, "stac_check.lint.Linter.check_links_title_field": {"tf": 1}, "stac_check.lint.Linter.check_links_self": {"tf": 1}, "stac_check.lint.Linter.check_catalog_file_name": {"tf": 1}}, "df": 15}}}}, "a": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}}}}}}, "i": {"docs": {}, "df": 0, "l": {"docs": {}, "df": 0, "d": {"docs": {"stac_check.lint.Linter.recursive_validation": {"tf": 1}}, "df": 1}}}}, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "e": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 2, "s": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 2}}}}}}, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.check_bloated_links": {"tf": 1}}, "df": 1}}}}}}, "u": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "t": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1.4142135623730951}}, "df": 1}}}}}}}, "j": {"docs": {}, "df": 0, "s": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter": {"tf": 5.916079783099616}, "stac_check.lint.Linter.load_data": {"tf": 2.23606797749979}, "stac_check.lint.Linter.check_links_assets": {"tf": 1}}, "df": 3, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "c": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "d": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.load_data": {"tf": 1}}, "df": 1}}}}}}}}}}}}}}}, "g": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "i": {"docs": {}, "df": 0, "n": {"docs": {}, "df": 0, "g": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}}}, "e": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_msg": {"tf": 1}}, "df": 1}}}}}}}, "t": {"docs": {"stac_check.lint.Linter": {"tf": 1}}, "df": 1}, "o": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "t": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "y": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.check_unlocated": {"tf": 1}, "stac_check.lint.Linter.check_geometry_null": {"tf": 1.4142135623730951}}, "df": 3}}}}}}}, "t": {"docs": {"stac_check.lint.Linter": {"tf": 4.795831523312719}}, "df": 1}, "i": {"docs": {}, "df": 0, "v": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "n": {"docs": {"stac_check.lint.Linter.validate_file": {"tf": 1}}, "df": 1}}}}}, "y": {"docs": {}, "df": 0, "a": {"docs": {}, "df": 0, "m": {"docs": {}, "df": 0, "l": {"docs": {"stac_check.lint.Linter": {"tf": 1.4142135623730951}, "stac_check.lint.Linter.parse_config": {"tf": 2.23606797749979}}, "df": 2, "e": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "r": {"docs": {}, "df": 0, "o": {"docs": {}, "df": 0, "r": {"docs": {"stac_check.lint.Linter.parse_config": {"tf": 1}}, "df": 1}}}}}}}}}, "k": {"docs": {}, "df": 0, "e": {"docs": {}, "df": 0, "y": {"docs": {}, "df": 0, "s": {"docs": {"stac_check.lint.Linter.create_best_practices_dict": {"tf": 1}}, "df": 1}}}}}}}, "pipeline": ["trimmer"], "_isPrebuiltIndex": true}; + + // mirrored in build-search-index.js (part 1) + // Also split on html tags. this is a cheap heuristic, but good enough. + elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/); + + let searchIndex; + if (docs._isPrebuiltIndex) { + console.info("using precompiled search index"); + searchIndex = elasticlunr.Index.load(docs); + } else { + console.time("building search index"); + // mirrored in build-search-index.js (part 2) + searchIndex = elasticlunr(function () { + this.pipeline.remove(elasticlunr.stemmer); + this.pipeline.remove(elasticlunr.stopWordFilter); + this.addField("qualname"); + this.addField("fullname"); + this.addField("annotation"); + this.addField("default_value"); + this.addField("signature"); + this.addField("bases"); + this.addField("doc"); + this.setRef("fullname"); + }); + for (let doc of docs) { + searchIndex.addDoc(doc); + } + console.timeEnd("building search index"); + } + + return (term) => searchIndex.search(term, { + fields: { + qualname: {boost: 4}, + fullname: {boost: 2}, + annotation: {boost: 2}, + default_value: {boost: 2}, + signature: {boost: 2}, + bases: {boost: 2}, + doc: {boost: 1}, + }, + expand: true + }); +})(); \ No newline at end of file diff --git a/pdoc/stac_check.html b/pdoc/stac_check.html new file mode 100644 index 0000000..cbea48a --- /dev/null +++ b/pdoc/stac_check.html @@ -0,0 +1,234 @@ + + + + + + + stac_check API documentation + + + + + + + + + +
+
+

+stac_check

+ + + + + +
+
+ + \ No newline at end of file diff --git a/pdoc/stac_check/cli.html b/pdoc/stac_check/cli.html index a951124..8200b0a 100644 --- a/pdoc/stac_check/cli.html +++ b/pdoc/stac_check/cli.html @@ -1,481 +1,728 @@ - - - -stac_check.cli API documentation - - - - - - - - - - + + + + stac_check.cli API documentation + + + + + + + -
-
-
-

Module stac_check.cli

-
-
-
- -Expand source code - -
import click
-from .lint import Linter
-import pkg_resources
-
-def link_asset_message(link_list:list, type: str, format: str) -> None:
-    """Prints a list of links or assets and any errors associated with them.
-
-    Args:
-        link_list (list): A list of links or assets.
-        type (str): The type of link or asset being processed.
-        format (str): The format or request being used.
-
-    Returns:
-        None.
-    """
-    if len(link_list) > 0:
-        click.secho(f"{type.upper()} {format} errors: ", fg="red")
-        for asset in link_list:
-            click.secho(f"    {asset}")
-    else:
-        click.secho(f"No {type.upper()} {format} errors!", fg="green")
-
-def recursive_message(linter: Linter) -> None:
-    """Displays messages related to the recursive validation of assets in a collection or catalog.
-
-    Args:
-        linter: An instance of the Linter class.
-
-    Returns:
-        None.
-    """
-    click.secho()
-    click.secho(f"Recursive: Validate all assets in a collection or catalog", bold=True)
-    click.secho(f"Max-depth = {linter.max_depth}")
-    click.secho("-------------------------")
-    for count, msg in enumerate(linter.validate_all):
-        click.secho(f"Asset {count+1} Validated: {msg['path']}", bg="white", fg="black")
-        click.secho()
-        if msg['valid_stac'] == True:
-            recursive_linter = Linter(msg["path"], recursive=0)
-            cli_message(recursive_linter)
-        else:
-            click.secho(f"Valid: {msg['valid_stac']}", fg='red')
-            click.secho("Schemas validated: ", fg="blue")
-            for schema in msg["schema"]:
-                click.secho(f"    {schema}")
-            click.secho(f"Error Type: {msg['error_type']}", fg='red')
-            click.secho(f"Error Message: {msg['error_message']}", fg='red')
-        click.secho("-------------------------")
-
-def intro_message(linter: Linter) -> None:
-    """Prints an introduction message for the stac-check tool.
-
-    The message includes the stac-check logo, the name of the tool, the version
-    of the STAC spec being validated, an update message, and the version of the
-    stac-validator being used.
-
-    Args:
-        linter (object): An instance of the Linter class, which is used to
-            obtain the version of the STAC spec being validated, the update
-            message, and the version of the stac-validator being used.
-
-    Returns:
-        None.
-    """
-    click.secho("""
- ____  ____  __    ___       ___  _  _  ____  ___  __ _ 
-/ ___)(_  _)/ _\  / __)___  / __)/ )( \(  __)/ __)(  / )
-\___ \  )( /    \( (__(___)( (__ ) __ ( ) _)( (__  )  ( 
-(____/ (__)\_/\_/ \___)     \___)\_)(_/(____)\___)(__\_)
-    """)
-
-    click.secho("stac-check: STAC spec validation and linting tool", bold=True)
-
-    click.secho()
-
-    if linter.version == "1.0.0":
-        click.secho(linter.set_update_message(), fg='green')
-    else:
-        click.secho(linter.set_update_message(), fg='red')
-
-    click.secho()
-
-    click.secho(f"Validator: stac-validator {linter.validator_version}", bg="blue", fg="white")
-
-    click.secho()
-
-def cli_message(linter: Linter) -> None:
-    """Prints various messages about the STAC object being validated.
-
-    Args:
-        linter: The `Linter` object containing information about 
-        the STAC object to be validated.
-
-    Returns:
-        None
-    """
-    if linter.valid_stac == True:
-        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg='green')
-    else:
-        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg='red')
-
-    ''' schemas validated for core object '''
-    click.secho()
-    if len(linter.schema) > 0:
-        click.secho("Schemas validated: ", fg="blue")
-        for schema in linter.schema:
-            click.secho(f"    {schema}")
-
-    ''' best practices message'''
-    click.secho()
-    for message in linter.best_practices_msg:
-        if message == linter.best_practices_msg[0]:
-            click.secho(message, bg='blue')
-        else:
-            click.secho(message, fg='red')
-
-    if linter.validate_all == True:
-        click.secho()
-        click.secho(f"Recursive validation has passed!", fg='blue')
-    elif linter.validate_all == False and linter.recursive:
-        click.secho()
-        click.secho(f"Recursive validation has failed!", fg='red')
-
-    if linter.invalid_asset_format is not None:
-        click.secho()
-        link_asset_message(linter.invalid_asset_format, "asset", "format")
-
-    if linter.invalid_asset_request is not None:
-        click.secho()
-        link_asset_message(linter.invalid_asset_request, "asset", "request")
-
-    if linter.invalid_link_format is not None:
-        click.secho()
-        link_asset_message(linter.invalid_link_format, "link", "format")
-
-    if linter.invalid_link_request is not None:
-        click.secho()
-        link_asset_message(linter.invalid_link_request, "link", "request")
-
-    if linter.error_type != "":
-        click.secho(f"Validation error type: ", fg="red")
-        click.secho(f"    {linter.error_type}")
-
-    if linter.error_msg != "":
-        click.secho(f"Validation error message: ", fg='red')
-        click.secho(f"    {linter.error_msg}")
-
-    click.secho(f"This object has {len(linter.data['links'])} links")
-
-    click.secho()
-
-    ### Stac validator response for reference
-    # click.secho(json.dumps(linter.message, indent=4))
-
-@click.option(
-    "--recursive",
-    "-r",
-    is_flag=True,
-    help="Recursively validate all related stac objects.",
-)
-@click.option(
-    "--max-depth",
-    "-m",
-    type=int,
-    help="Maximum depth to traverse when recursing. Omit this argument to get full recursion. Ignored if `recursive == False`.",
-)
-@click.option(
-    "-a", "--assets", is_flag=True, help="Validate assets for format and response."
-)
-@click.option(
-    "-l", "--links", is_flag=True, help="Validate links for format and response."
-)
-@click.command()
-@click.argument('file')
-@click.version_option(version=pkg_resources.require("stac-check")[0].version)
-def main(file, recursive, max_depth, assets, links):
-    linter = Linter(file, assets=assets, links=links, recursive=recursive, max_depth=max_depth)
-    intro_message(linter)
-    if recursive > 0:
-        recursive_message(linter)
-    else:
-        cli_message(linter)
-
-
-
-
-
-
-
-

Functions

-
-
-def cli_message(linter: Linter) ‑> NoneType -
-
-

Prints various messages about the STAC object being validated.

-

Args

-
-
linter
-
The Linter object containing information about
-
-

the STAC object to be validated.

-

Returns

-

None

-
- -Expand source code - -
def cli_message(linter: Linter) -> None:
-    """Prints various messages about the STAC object being validated.
-
-    Args:
-        linter: The `Linter` object containing information about 
-        the STAC object to be validated.
-
-    Returns:
-        None
-    """
-    if linter.valid_stac == True:
-        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg='green')
-    else:
-        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg='red')
-
-    ''' schemas validated for core object '''
-    click.secho()
-    if len(linter.schema) > 0:
-        click.secho("Schemas validated: ", fg="blue")
-        for schema in linter.schema:
-            click.secho(f"    {schema}")
-
-    ''' best practices message'''
-    click.secho()
-    for message in linter.best_practices_msg:
-        if message == linter.best_practices_msg[0]:
-            click.secho(message, bg='blue')
-        else:
-            click.secho(message, fg='red')
-
-    if linter.validate_all == True:
-        click.secho()
-        click.secho(f"Recursive validation has passed!", fg='blue')
-    elif linter.validate_all == False and linter.recursive:
-        click.secho()
-        click.secho(f"Recursive validation has failed!", fg='red')
-
-    if linter.invalid_asset_format is not None:
-        click.secho()
-        link_asset_message(linter.invalid_asset_format, "asset", "format")
-
-    if linter.invalid_asset_request is not None:
-        click.secho()
-        link_asset_message(linter.invalid_asset_request, "asset", "request")
-
-    if linter.invalid_link_format is not None:
-        click.secho()
-        link_asset_message(linter.invalid_link_format, "link", "format")
-
-    if linter.invalid_link_request is not None:
-        click.secho()
-        link_asset_message(linter.invalid_link_request, "link", "request")
-
-    if linter.error_type != "":
-        click.secho(f"Validation error type: ", fg="red")
-        click.secho(f"    {linter.error_type}")
-
-    if linter.error_msg != "":
-        click.secho(f"Validation error message: ", fg='red')
-        click.secho(f"    {linter.error_msg}")
-
-    click.secho(f"This object has {len(linter.data['links'])} links")
-
-    click.secho()
-
-    ### Stac validator response for reference
-    # click.secho(json.dumps(linter.message, indent=4))
-
-
-
-def intro_message(linter: Linter) ‑> NoneType -
-
-

Prints an introduction message for the stac-check tool.

+ +
+
+

+stac_check.cli

+ + + + + + +
  1import importlib.metadata
+  2
+  3import click
+  4
+  5from .lint import Linter
+  6from .logo import logo
+  7
+  8
+  9def link_asset_message(
+ 10    link_list: list, type: str, format: str, healthy_msg: bool
+ 11) -> None:
+ 12    """Prints a list of links or assets and any errors associated with them.
+ 13
+ 14    Args:
+ 15        link_list (list): A list of links or assets.
+ 16        type (str): The type of link or asset being processed.
+ 17        format (str): The format or request being used.
+ 18        healthy_msg (bool): Whether to display "No TYPE errors!" or not
+ 19
+ 20    Returns:
+ 21        None.
+ 22    """
+ 23    if len(link_list) > 0:
+ 24        click.secho(f"{type.upper()} {format} errors: ", fg="red")
+ 25        for asset in link_list:
+ 26            click.secho(f"    {asset}")
+ 27    elif healthy_msg:
+ 28        click.secho(f"No {type.upper()} {format} errors!", fg="green")
+ 29
+ 30
+ 31def recursive_message(linter: Linter) -> None:
+ 32    """Displays messages related to the recursive validation of assets in a collection or catalog.
+ 33
+ 34    Args:
+ 35        linter: An instance of the Linter class.
+ 36
+ 37    Returns:
+ 38        None.
+ 39    """
+ 40    click.secho()
+ 41    click.secho("Recursive: Validate all assets in a collection or catalog", bold=True)
+ 42    click.secho(f"Max-depth = {linter.max_depth}")
+ 43    click.secho("-------------------------")
+ 44    for count, msg in enumerate(linter.validate_all):
+ 45        click.secho(
+ 46            f"Asset {count + 1} Validated: {msg['path']}", bg="white", fg="black"
+ 47        )
+ 48        click.secho()
+ 49        if msg["valid_stac"] == True:
+ 50            recursive_linter = Linter(msg["path"], recursive=True)
+ 51            cli_message(recursive_linter)
+ 52        else:
+ 53            click.secho(f"Valid: {msg['valid_stac']}", fg="red")
+ 54            click.secho("Schemas validated: ", fg="blue")
+ 55            for schema in msg["schema"]:
+ 56                click.secho(f"    {schema}")
+ 57            click.secho(f"Error Type: {msg['error_type']}", fg="red")
+ 58            click.secho(f"Error Message: {msg['error_message']}", fg="red")
+ 59        click.secho("-------------------------")
+ 60
+ 61
+ 62def intro_message(linter: Linter) -> None:
+ 63    """Prints an introduction message for the stac-check tool.
+ 64
+ 65    The message includes the stac-check logo, the name of the tool, the version
+ 66    of the STAC spec being validated, an update message, and the version of the
+ 67    stac-validator being used.
+ 68
+ 69    Args:
+ 70        linter (object): An instance of the Linter class, which is used to
+ 71            obtain the version of the STAC spec being validated, the update
+ 72            message, and the version of the stac-validator being used.
+ 73
+ 74    Returns:
+ 75        None.
+ 76    """
+ 77    click.secho(logo)
+ 78
+ 79    click.secho("stac-check: STAC spec validation and linting tool", bold=True)
+ 80
+ 81    click.secho()
+ 82
+ 83    if linter.version == "1.0.0":
+ 84        click.secho(linter.set_update_message(), fg="green")
+ 85    else:
+ 86        click.secho(linter.set_update_message(), fg="red")
+ 87
+ 88    click.secho()
+ 89
+ 90    click.secho(
+ 91        f"Validator: stac-validator {linter.validator_version}", bg="blue", fg="white"
+ 92    )
+ 93
+ 94    click.secho()
+ 95
+ 96
+ 97def cli_message(linter: Linter) -> None:
+ 98    """Prints various messages about the STAC object being validated.
+ 99
+100    Args:
+101        linter: The `Linter` object containing information about
+102        the STAC object to be validated.
+103
+104    Returns:
+105        None
+106    """
+107    if linter.valid_stac == True:
+108        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg="green")
+109    else:
+110        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg="red")
+111
+112    """ schemas validated for core object """
+113    click.secho()
+114    if len(linter.schema) > 0:
+115        click.secho("Schemas validated: ", fg="blue")
+116        for schema in linter.schema:
+117            click.secho(f"    {schema}")
+118
+119    """ best practices message"""
+120    click.secho()
+121    for message in linter.best_practices_msg:
+122        if message == linter.best_practices_msg[0]:
+123            click.secho(message, bg="blue")
+124        else:
+125            click.secho(message, fg="red")
+126
+127    if linter.validate_all == True:
+128        click.secho()
+129        click.secho("Recursive validation has passed!", fg="blue")
+130    elif linter.validate_all == False and linter.recursive:
+131        click.secho()
+132        click.secho("Recursive validation has failed!", fg="red")
+133
+134    if linter.invalid_asset_format is not None:
+135        click.secho()
+136        link_asset_message(linter.invalid_asset_format, "asset", "format", True)
+137
+138    if linter.invalid_asset_request is not None:
+139        click.secho()
+140        link_asset_message(
+141            linter.invalid_asset_request, "asset", "request", linter.assets_open_urls
+142        )
+143
+144    if linter.invalid_link_format is not None:
+145        click.secho()
+146        link_asset_message(linter.invalid_link_format, "link", "format", True)
+147
+148    if linter.invalid_link_request is not None:
+149        click.secho()
+150        link_asset_message(linter.invalid_link_request, "link", "request", True)
+151
+152    if linter.error_type != "":
+153        click.secho("Validation error type: ", fg="red")
+154        click.secho(f"    {linter.error_type}")
+155
+156    if linter.error_msg != "":
+157        click.secho("Validation error message: ", fg="red")
+158        click.secho(f"    {linter.error_msg}")
+159
+160    click.secho(f"This object has {len(linter.data['links'])} links")
+161
+162    click.secho()
+163
+164    # Stac validator response for reference
+165    # click.secho(json.dumps(linter.message, indent=4))
+166
+167
+168@click.option(
+169    "--recursive",
+170    "-r",
+171    is_flag=True,
+172    help="Recursively validate all related stac objects.",
+173)
+174@click.option(
+175    "--max-depth",
+176    "-m",
+177    type=int,
+178    help="Maximum depth to traverse when recursing. Omit this argument to get full recursion. Ignored if `recursive == False`.",
+179)
+180@click.option(
+181    "-a", "--assets", is_flag=True, help="Validate assets for format and response."
+182)
+183@click.option(
+184    "-l", "--links", is_flag=True, help="Validate links for format and response."
+185)
+186@click.option(
+187    "--no-assets-urls",
+188    is_flag=True,
+189    help="Disables the opening of href links when validating assets (enabled by default).",
+190)
+191@click.option(
+192    "--header",
+193    type=(str, str),
+194    multiple=True,
+195    help="HTTP header to include in the requests. Can be used multiple times.",
+196)
+197@click.command()
+198@click.argument("file")
+199@click.version_option(version=importlib.metadata.distribution("stac-check").version)
+200def main(file, recursive, max_depth, assets, links, no_assets_urls, header):
+201    linter = Linter(
+202        file,
+203        assets=assets,
+204        links=links,
+205        recursive=recursive,
+206        max_depth=max_depth,
+207        assets_open_urls=not no_assets_urls,
+208        headers=dict(header),
+209    )
+210    intro_message(linter)
+211    if recursive > 0:
+212        recursive_message(linter)
+213    else:
+214        cli_message(linter)
+
+ + +
+ +
+ +
+ + def + recursive_message(linter: stac_check.lint.Linter) -> None: + + + +
+ +
32def recursive_message(linter: Linter) -> None:
+33    """Displays messages related to the recursive validation of assets in a collection or catalog.
+34
+35    Args:
+36        linter: An instance of the Linter class.
+37
+38    Returns:
+39        None.
+40    """
+41    click.secho()
+42    click.secho("Recursive: Validate all assets in a collection or catalog", bold=True)
+43    click.secho(f"Max-depth = {linter.max_depth}")
+44    click.secho("-------------------------")
+45    for count, msg in enumerate(linter.validate_all):
+46        click.secho(
+47            f"Asset {count + 1} Validated: {msg['path']}", bg="white", fg="black"
+48        )
+49        click.secho()
+50        if msg["valid_stac"] == True:
+51            recursive_linter = Linter(msg["path"], recursive=True)
+52            cli_message(recursive_linter)
+53        else:
+54            click.secho(f"Valid: {msg['valid_stac']}", fg="red")
+55            click.secho("Schemas validated: ", fg="blue")
+56            for schema in msg["schema"]:
+57                click.secho(f"    {schema}")
+58            click.secho(f"Error Type: {msg['error_type']}", fg="red")
+59            click.secho(f"Error Message: {msg['error_message']}", fg="red")
+60        click.secho("-------------------------")
+
+ + +

Displays messages related to the recursive validation of assets in a collection or catalog.

+ +

Args: + linter: An instance of the Linter class.

+ +

Returns: + None.

+
+ + +
+
+ +
+ + def + intro_message(linter: stac_check.lint.Linter) -> None: + + + +
+ +
63def intro_message(linter: Linter) -> None:
+64    """Prints an introduction message for the stac-check tool.
+65
+66    The message includes the stac-check logo, the name of the tool, the version
+67    of the STAC spec being validated, an update message, and the version of the
+68    stac-validator being used.
+69
+70    Args:
+71        linter (object): An instance of the Linter class, which is used to
+72            obtain the version of the STAC spec being validated, the update
+73            message, and the version of the stac-validator being used.
+74
+75    Returns:
+76        None.
+77    """
+78    click.secho(logo)
+79
+80    click.secho("stac-check: STAC spec validation and linting tool", bold=True)
+81
+82    click.secho()
+83
+84    if linter.version == "1.0.0":
+85        click.secho(linter.set_update_message(), fg="green")
+86    else:
+87        click.secho(linter.set_update_message(), fg="red")
+88
+89    click.secho()
+90
+91    click.secho(
+92        f"Validator: stac-validator {linter.validator_version}", bg="blue", fg="white"
+93    )
+94
+95    click.secho()
+
+ + +

Prints an introduction message for the stac-check tool.

+

The message includes the stac-check logo, the name of the tool, the version of the STAC spec being validated, an update message, and the version of the stac-validator being used.

-

Args

-
-
linter : object
-
An instance of the Linter class, which is used to -obtain the version of the STAC spec being validated, the update -message, and the version of the stac-validator being used.
-
-

Returns

-

None.

-
- -Expand source code - -
def intro_message(linter: Linter) -> None:
-    """Prints an introduction message for the stac-check tool.
-
-    The message includes the stac-check logo, the name of the tool, the version
-    of the STAC spec being validated, an update message, and the version of the
-    stac-validator being used.
-
-    Args:
-        linter (object): An instance of the Linter class, which is used to
-            obtain the version of the STAC spec being validated, the update
-            message, and the version of the stac-validator being used.
-
-    Returns:
-        None.
-    """
-    click.secho("""
- ____  ____  __    ___       ___  _  _  ____  ___  __ _ 
-/ ___)(_  _)/ _\  / __)___  / __)/ )( \(  __)/ __)(  / )
-\___ \  )( /    \( (__(___)( (__ ) __ ( ) _)( (__  )  ( 
-(____/ (__)\_/\_/ \___)     \___)\_)(_/(____)\___)(__\_)
-    """)
-
-    click.secho("stac-check: STAC spec validation and linting tool", bold=True)
-
-    click.secho()
-
-    if linter.version == "1.0.0":
-        click.secho(linter.set_update_message(), fg='green')
-    else:
-        click.secho(linter.set_update_message(), fg='red')
-
-    click.secho()
-
-    click.secho(f"Validator: stac-validator {linter.validator_version}", bg="blue", fg="white")
-
-    click.secho()
-
-
- -
-

Prints a list of links or assets and any errors associated with them.

-

Args

-
-
link_list : list
-
A list of links or assets.
-
type : str
-
The type of link or asset being processed.
-
format : str
-
The format or request being used.
-
-

Returns

-

None.

-
- -Expand source code - -
def link_asset_message(link_list:list, type: str, format: str) -> None:
-    """Prints a list of links or assets and any errors associated with them.
-
-    Args:
-        link_list (list): A list of links or assets.
-        type (str): The type of link or asset being processed.
-        format (str): The format or request being used.
-
-    Returns:
-        None.
-    """
-    if len(link_list) > 0:
-        click.secho(f"{type.upper()} {format} errors: ", fg="red")
-        for asset in link_list:
-            click.secho(f"    {asset}")
-    else:
-        click.secho(f"No {type.upper()} {format} errors!", fg="green")
-
-
-
-def recursive_message(linter: Linter) ‑> NoneType -
-
-

Displays messages related to the recursive validation of assets in a collection or catalog.

-

Args

-
-
linter
-
An instance of the Linter class.
-
-

Returns

-

None.

-
- -Expand source code - -
def recursive_message(linter: Linter) -> None:
-    """Displays messages related to the recursive validation of assets in a collection or catalog.
-
-    Args:
-        linter: An instance of the Linter class.
-
-    Returns:
-        None.
-    """
-    click.secho()
-    click.secho(f"Recursive: Validate all assets in a collection or catalog", bold=True)
-    click.secho(f"Max-depth = {linter.max_depth}")
-    click.secho("-------------------------")
-    for count, msg in enumerate(linter.validate_all):
-        click.secho(f"Asset {count+1} Validated: {msg['path']}", bg="white", fg="black")
-        click.secho()
-        if msg['valid_stac'] == True:
-            recursive_linter = Linter(msg["path"], recursive=0)
-            cli_message(recursive_linter)
-        else:
-            click.secho(f"Valid: {msg['valid_stac']}", fg='red')
-            click.secho("Schemas validated: ", fg="blue")
-            for schema in msg["schema"]:
-                click.secho(f"    {schema}")
-            click.secho(f"Error Type: {msg['error_type']}", fg='red')
-            click.secho(f"Error Message: {msg['error_message']}", fg='red')
-        click.secho("-------------------------")
-
-
-
-
-
-
-
- -
- - + + + +
+ +
+ + def + cli_message(linter: stac_check.lint.Linter) -> None: + + + +
+ +
 98def cli_message(linter: Linter) -> None:
+ 99    """Prints various messages about the STAC object being validated.
+100
+101    Args:
+102        linter: The `Linter` object containing information about
+103        the STAC object to be validated.
+104
+105    Returns:
+106        None
+107    """
+108    if linter.valid_stac == True:
+109        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg="green")
+110    else:
+111        click.secho(f"Valid {linter.asset_type}: {linter.valid_stac}", fg="red")
+112
+113    """ schemas validated for core object """
+114    click.secho()
+115    if len(linter.schema) > 0:
+116        click.secho("Schemas validated: ", fg="blue")
+117        for schema in linter.schema:
+118            click.secho(f"    {schema}")
+119
+120    """ best practices message"""
+121    click.secho()
+122    for message in linter.best_practices_msg:
+123        if message == linter.best_practices_msg[0]:
+124            click.secho(message, bg="blue")
+125        else:
+126            click.secho(message, fg="red")
+127
+128    if linter.validate_all == True:
+129        click.secho()
+130        click.secho("Recursive validation has passed!", fg="blue")
+131    elif linter.validate_all == False and linter.recursive:
+132        click.secho()
+133        click.secho("Recursive validation has failed!", fg="red")
+134
+135    if linter.invalid_asset_format is not None:
+136        click.secho()
+137        link_asset_message(linter.invalid_asset_format, "asset", "format", True)
+138
+139    if linter.invalid_asset_request is not None:
+140        click.secho()
+141        link_asset_message(
+142            linter.invalid_asset_request, "asset", "request", linter.assets_open_urls
+143        )
+144
+145    if linter.invalid_link_format is not None:
+146        click.secho()
+147        link_asset_message(linter.invalid_link_format, "link", "format", True)
+148
+149    if linter.invalid_link_request is not None:
+150        click.secho()
+151        link_asset_message(linter.invalid_link_request, "link", "request", True)
+152
+153    if linter.error_type != "":
+154        click.secho("Validation error type: ", fg="red")
+155        click.secho(f"    {linter.error_type}")
+156
+157    if linter.error_msg != "":
+158        click.secho("Validation error message: ", fg="red")
+159        click.secho(f"    {linter.error_msg}")
+160
+161    click.secho(f"This object has {len(linter.data['links'])} links")
+162
+163    click.secho()
+164
+165    # Stac validator response for reference
+166    # click.secho(json.dumps(linter.message, indent=4))
+
+ + +

Prints various messages about the STAC object being validated.

+ +

Args: + linter: The Linter object containing information about + the STAC object to be validated.

+ +

Returns: + None

+
+ + +
+ + \ No newline at end of file diff --git a/pdoc/stac_check/index.html b/pdoc/stac_check/index.html deleted file mode 100644 index c6d4992..0000000 --- a/pdoc/stac_check/index.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - -stac_check API documentation - - - - - - - - - - - -
- - -
- - - \ No newline at end of file diff --git a/pdoc/stac_check/lint.html b/pdoc/stac_check/lint.html index f64659e..3269e4b 100644 --- a/pdoc/stac_check/lint.html +++ b/pdoc/stac_check/lint.html @@ -1,2291 +1,2990 @@ - - - -stac_check.lint API documentation - - - - - - - - - - + + + + stac_check.lint API documentation + + + + + + + -
-
-
-

Module stac_check.lint

-
-
-
- -Expand source code - -
import pkg_resources
-from stac_validator.validate import StacValidate
-from stac_validator.utilities import is_valid_url
-import json
-import yaml
-import os
-from dataclasses import dataclass
-import requests
-from typing import Optional, Union, Dict, Any, List
-from dotenv import load_dotenv
-import pkg_resources
-
-load_dotenv()
-
-@dataclass
-class Linter:
-    """A class for linting STAC JSON files and generating validation messages.
-
-    Args:
-        item (Union[str, dict]): A URL, file name, or dictionary representing a STAC JSON file.
-        config_file (Optional[str], optional): A path to a YAML configuration file. Defaults to None.
-        assets (bool, optional): A boolean value indicating whether to validate assets. Defaults to False.
-        links (bool, optional): A boolean value indicating whether to validate links. Defaults to False.
-        recursive (bool, optional): A boolean value indicating whether to perform recursive validation. Defaults to False.
-        max_depth (Optional[int], optional): An optional integer indicating the maximum depth to validate recursively. Defaults to None.
-
-    Attributes:
-        data (dict): A dictionary representing the STAC JSON file.
-        message (dict): A dictionary containing the validation message for the STAC JSON file.
-        config (dict): A dictionary containing the configuration settings.
-        asset_type (str): A string representing the asset type, if one is specified.
-        version (str): A string representing the version of the STAC standard used in the STAC JSON file.
-        validator_version (str): A string representing the version of the STAC validator used to validate the STAC JSON file.
-        validate_all (dict): A dictionary containing the validation message for all STAC JSON files found recursively, if recursive validation was performed.
-        valid_stac (bool): A boolean value indicating whether the STAC JSON file is valid.
-        error_type (str): A string representing the type of error in the STAC JSON file, if one exists.
-        error_msg (str): A string representing the error message in the STAC JSON file, if one exists.
-        invalid_asset_format (List[str]): A list of URLs with invalid asset formats, if assets were validated.
-        invalid_asset_request (List[str]): A list of URLs with invalid asset requests, if assets were validated.
-        invalid_link_format (List[str]): A list of URLs with invalid link formats, if links were validated.
-        invalid_link_request (List[str]): A list of URLs with invalid link requests, if links were validated.
-        schema (List[str]): A list of the STAC JSON file's JSON schema files.
-        object_id (str): A string representing the STAC JSON file's ID.
-        file_name (str): A string representing the name of the file containing the STAC JSON data.
-        best_practices_msg (str): A string representing best practices messages for the STAC JSON file.
-
-    Methods:
-        parse_config(config_file: Optional[str] = None) -> Dict:
-            Parses a YAML configuration file and returns a dictionary with the configuration settings.
-
-        def get_asset_name(self, file: Union[str, Dict] = None) -> str:
-            Returns the name of a file.
-
-        load_data(self, file: Union[str, Dict]) -> Dict:
-            Loads a STAC JSON file from a URL or file path and returns a dictionary representation.
-
-        validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
-            Validates a STAC JSON file and returns a dictionary with the validation message.
-
-        recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
-            Validates a STAC JSON file recursively and returns a dictionary with the validation message.
-
-        set_update_message(self) -> str:
-            Sets a message regarding the recommended version of the STAC JSON file standard.
-
-        check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
-            Checks whether the STAC JSON file has links or assets with invalid formats or requests.
-
-        check_error_type(self) -> str:                  
-            Checks whether the STAC JSON file has an error type.
-
-        check_error_message(self) -> str:
-            Checks whether the STAC JSON file has an error message. 
-
-        def check_summaries(self) -> bool:
-            Checks whether the STAC JSON file has summaries.
-
-        check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
-            Checks whether the STAC JSON file has bloated links.
-
-        check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
-            Checks whether the STAC JSON file has bloated metadata.
-
-        check_datetime_null(self) -> bool:
-            Checks whether the STAC JSON file has a null datetime.
-
-        check_unlocated(self) -> bool:
-            Checks whether the STAC JSON file has unlocated items.
-
-        check_geometry_null(self) -> bool:
-            Checks whether the STAC JSON file has a null geometry.  
-
-        check_searchable_identifiers(self) -> bool: 
-            Checks whether the STAC JSON file has searchable identifiers.
-
-        check_percent_encoded(self) -> bool:
-            Checks whether the STAC JSON file has percent-encoded characters.
-
-        check_thumbnail(self) -> bool:
-            Checks whether the STAC JSON file has a thumbnail.
-
-        check_links_title_field(self) -> bool:
-            Checks whether the STAC JSON file has a title field in its links.
-
-        check_links_self(self) -> bool:
-            Checks whether the STAC JSON file has a self link.
-
-        check_item_id_file_name(self) -> bool:
-            Checks whether the filename of an Item conforms to the STAC specification.
-
-        check_catalog_file_name(self) -> str:
-            Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
-
-        create_best_practices_dict(self) -> Dict[str, Any]:
-            Creates a dictionary with best practices recommendations for the STAC JSON file.
-
-        create_best_practices_msg(self) -> List[str]:
-            Creates a message with best practices recommendations for the STAC JSON file.
-    """
-    item: Union[str, dict] # url, file name, or dictionary
-    config_file: Optional[str] = None
-    assets: bool = False
-    links: bool = False
-    recursive: bool = False
-    max_depth: Optional[int] = None
-
-    def __post_init__(self):
-        self.data = self.load_data(self.item)
-        self.message = self.validate_file(self.item)
-        self.config = self.parse_config(self.config_file)
-        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 = pkg_resources.require("stac-validator")[0].version
-        self.validate_all = self.recursive_validation(self.item)
-        self.valid_stac = self.message["valid_stac"]
-        self.error_type = self.check_error_type()
-        self.error_msg = self.check_error_message()
-        self.invalid_asset_format = self.check_links_assets(10, "assets", "format") if self.assets else None
-        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.message["schema"] if "schema" in self.message else []
-        self.object_id = self.data["id"] if "id" in self.data else ""
-        self.file_name = self.get_asset_name(self.item)
-        self.best_practices_msg = self.create_best_practices_msg()
-
-    @staticmethod
-    def parse_config(config_file: Optional[str] = None) -> Dict:
-        """Parse the configuration file for STAC checks.
-
-        The method first looks for a file path specified in the `STAC_CHECK_CONFIG`
-        environment variable. If the variable is defined, the method loads the
-        YAML configuration file located at that path. Otherwise, it loads the default
-        configuration file packaged with the `stac-check` module.
-
-        If `config_file` is specified, the method also loads the YAML configuration
-        file located at that path and merges its contents with the default or
-        environment-based configuration.
-
-        Args:
-            config_file (str): The path to the YAML configuration file.
-
-        Returns:
-            A dictionary containing the parsed configuration values.
-
-        Raises:
-            IOError: If `config_file` is specified but cannot be read.
-            yaml.YAMLError: If any YAML syntax errors occur while parsing the
-                configuration file(s).
-        """
-        default_config_file = os.getenv("STAC_CHECK_CONFIG")
-        if default_config_file:
-            with open(default_config_file) as f:
-                default_config = yaml.load(f, Loader=yaml.FullLoader)
-        else:
-            with pkg_resources.resource_stream(__name__, "stac-check.config.yml") as f:
-                default_config = yaml.load(f, Loader=yaml.FullLoader)
-        if config_file:
-            with open(config_file) as f:
-                config = yaml.load(f, Loader=yaml.FullLoader)
-            default_config.update(config)
-            
-        return default_config
-
-    def get_asset_name(self, file: Union[str, Dict] = None) -> str:
-        """Extracts the name of an asset from its file path or from a STAC item asset dictionary.
-
-        Args:
-            file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the
-                asset as specified in a STAC item's `assets` property.
-
-        Returns:
-            A string containing the name of the asset.
-
-        Raises:
-            TypeError: If the input `file` is not a string or a dictionary.
-        """
-        if isinstance(file, str):
-            return os.path.basename(file).split('.')[0]
-        else:
-            return file["id"]
-
-    def load_data(self, file: Union[str, Dict]) -> Dict:
-        """Loads JSON data from a file or URL.
-
-        Args:
-            file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.
-
-        Returns:
-            A dictionary containing the loaded JSON data.
-
-        Raises:
-            TypeError: If the input `file` is not a string or dictionary.
-            ValueError: If `file` is a string that doesn't represent a valid URL or file path.
-            requests.exceptions.RequestException: If there is an error making a request to a URL.
-            JSONDecodeError: If the JSON data cannot be decoded.
-            FileNotFoundError: If the specified file cannot be found.
-        """
-
-        if isinstance(file, str):
-            if is_valid_url(file):
-                resp = requests.get(file)
-                data = resp.json()
-            else:
-                with open(file) as json_file:
-                    data = json.load(json_file)
-            return data
-        else:
-            return file
-
-    def validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
-        """Validates the given file path or STAC dictionary against the validation schema.
-
-        Args:
-            file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC
-                item.
-
-        Returns:
-            A dictionary containing the results of the validation, including the status of the validation and any errors
-            encountered.
-
-        Raises:
-            ValueError: If `file` is not a valid file path or STAC dictionary.
-        """
-        if isinstance(file, str):
-            stac = StacValidate(file, links=self.links, assets=self.assets)
-            stac.run()
-        elif isinstance(file, dict):
-            stac = StacValidate()
-            stac.validate_dict(file)
-        else:
-            raise ValueError("Input must be a file path or STAC dictionary.")
-        return stac.message[0]
-
-    def recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
-        """Recursively validate a STAC item or catalog file and its child items.
-
-        Args:
-            file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a
-                dictionary representing the STAC item or catalog.
-
-        Returns:
-            A string containing the validation message.
-
-        Raises:
-            TypeError: If the input `file` is not a string or a dictionary.
-        """
-        if self.recursive:
-            if isinstance(file, str):
-                stac = StacValidate(file, recursive=True, max_depth=self.max_depth)
-                stac.run()
-            else:
-                stac = StacValidate(recursive=True, max_depth=self.max_depth)
-                stac.validate_dict(file)
-            return stac.message
-
-    def set_update_message(self) -> str:
-        """Returns a message for users to update their STAC version.
-
-        Returns:
-            A string containing a message for users to update their STAC version.
-        """
-        if self.version != "1.0.0":
-            return f"Please upgrade from version {self.version} to version 1.0.0!"
-        else:
-            return "Thanks for using STAC version 1.0.0!"
-
-    def check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
-        """Checks the links and assets in the STAC catalog and returns a list of invalid links of a specified type and format.
-
-        Args:
-            num_links (int): The maximum number of invalid links to return.
-            url_type (str): The type of URL to check, which can be either 'self' or 'external'.
-            format_type (str): The format of the URL to check, which can be either 'html' or 'json'.
-
-        Returns:
-            A list of invalid links of the specified type and format. If there are no invalid links, an empty list is returned.
-        """
-        links = []
-        if f"{url_type}_validated" in self.message:
-            for invalid_request_url in self.message[f"{url_type}_validated"][f"{format_type}_invalid"]:
-                if invalid_request_url not in links and 'http' in invalid_request_url:
-                    links.append(invalid_request_url)
-                num_links = num_links - 1
-                if num_links == 0:
-                    return links
-        return links
-
-    def check_error_type(self) -> str:
-        """Returns the error type of a STAC validation if it exists in the validation message, 
-        and an empty string otherwise.
-
-        Returns:
-            str: A string containing the error type of a STAC validation if it exists in the validation message, and an
-            empty string otherwise.
-        """
-        if "error_type" in self.message:
-            return self.message["error_type"]
-        else:
-            return ""
-
-    def check_error_message(self) -> str:
-        """Checks whether the `message` attribute contains an `error_message` field.
-
-        Returns:
-            A string containing the value of the `error_message` field, or an empty string if the field is not present.
-        """
-        if "error_message" in self.message:
-            return self.message["error_message"]
-        else:
-            return ""
-
-    def check_summaries(self) -> bool:
-        """Check if a Collection asset has a "summaries" property.
-
-        Returns:
-            A boolean indicating whether the Collection asset has a "summaries" property.
-        """
-        if self.asset_type == "COLLECTION":
-            return "summaries" in self.data
-
-    def check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
-        """Checks if the number of links in the STAC data exceeds a certain maximum.
-
-        Args:
-            max_links (Optional[int]): The maximum number of links that the STAC data is allowed to have. Default is 20.
-
-        Returns:
-            bool: A boolean indicating if the number of links in the STAC data exceeds the specified maximum.
-        """
-        if "links" in self.data:
-            return len(self.data["links"]) > max_links
-
-    def check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
-        """Checks whether a STAC item's metadata contains too many properties.
-
-        Args:
-            max_properties (int, optional): The maximum number of properties that the metadata can contain before it is
-                considered too bloated. Defaults to 20.
-
-        Returns:
-            bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by
-                `max_properties`, False otherwise.
-        """
-        if "properties" in self.data:
-            return len(self.data["properties"].keys()) > max_properties
-        return False
-
-    def check_datetime_null(self) -> bool:
-        """Checks if the STAC item has a null datetime property.
-
-        Returns:
-            bool: A boolean indicating whether the datetime property is null (True) or not (False).
-        """
-        if "properties" in self.data:
-            if "datetime" in self.data["properties"]:
-                if self.data["properties"]["datetime"] == None:
-                    return True
-        else:
-            return False
-        return False
-
-    def check_unlocated(self) -> bool:
-        """Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.
-
-        Returns:
-            bool: True if the STAC item is unlocated, False otherwise.
-        """
-        if "geometry" in self.data:
-            return self.data["geometry"] is None and self.data["bbox"] is not None
-
-    def check_geometry_null(self) -> bool:
-        """Checks if a STAC item has a null geometry property.
+    
+    
+
+

+stac_check.lint

+ + + + + + +
  1import importlib.metadata
+  2import importlib.resources
+  3import json
+  4import os
+  5from dataclasses import dataclass, field
+  6from typing import Any, Dict, List, Optional, Union
+  7
+  8import requests
+  9import yaml
+ 10from dotenv import load_dotenv
+ 11from stac_validator.utilities import is_valid_url
+ 12from stac_validator.validate import StacValidate
+ 13
+ 14load_dotenv()
+ 15
+ 16
+ 17@dataclass
+ 18class Linter:
+ 19    """A class for linting STAC JSON files and generating validation messages.
+ 20
+ 21    Args:
+ 22        item (Union[str, dict]): A URL, file name, or dictionary representing a STAC JSON file.
+ 23        config_file (Optional[str], optional): A path to a YAML configuration file. Defaults to None.
+ 24        assets (bool, optional): A boolean value indicating whether to validate assets. Defaults to False.
+ 25        links (bool, optional): A boolean value indicating whether to validate links. Defaults to False.
+ 26        recursive (bool, optional): A boolean value indicating whether to perform recursive validation. Defaults to False.
+ 27        max_depth (Optional[int], optional): An optional integer indicating the maximum depth to validate recursively. Defaults to None.
+ 28        assets_open_urls (bool): Whether to open assets URLs when validating assets. Defaults to True.
+ 29        headers (dict): HTTP headers to include in the requests.
+ 30
+ 31    Attributes:
+ 32        data (dict): A dictionary representing the STAC JSON file.
+ 33        message (dict): A dictionary containing the validation message for the STAC JSON file.
+ 34        config (dict): A dictionary containing the configuration settings.
+ 35        asset_type (str): A string representing the asset type, if one is specified.
+ 36        version (str): A string representing the version of the STAC standard used in the STAC JSON file.
+ 37        validator_version (str): A string representing the version of the STAC validator used to validate the STAC JSON file.
+ 38        validate_all (dict): A dictionary containing the validation message for all STAC JSON files found recursively, if recursive validation was performed.
+ 39        valid_stac (bool): A boolean value indicating whether the STAC JSON file is valid.
+ 40        error_type (str): A string representing the type of error in the STAC JSON file, if one exists.
+ 41        error_msg (str): A string representing the error message in the STAC JSON file, if one exists.
+ 42        invalid_asset_format (List[str]): A list of URLs with invalid asset formats, if assets were validated.
+ 43        invalid_asset_request (List[str]): A list of URLs with invalid asset requests, if assets were validated.
+ 44        invalid_link_format (List[str]): A list of URLs with invalid link formats, if links were validated.
+ 45        invalid_link_request (List[str]): A list of URLs with invalid link requests, if links were validated.
+ 46        schema (List[str]): A list of the STAC JSON file's JSON schema files.
+ 47        object_id (str): A string representing the STAC JSON file's ID.
+ 48        file_name (str): A string representing the name of the file containing the STAC JSON data.
+ 49        best_practices_msg (str): A string representing best practices messages for the STAC JSON file.
+ 50
+ 51    Methods:
+ 52        parse_config(config_file: Optional[str] = None) -> Dict:
+ 53            Parses a YAML configuration file and returns a dictionary with the configuration settings.
+ 54
+ 55        def get_asset_name(self, file: Union[str, Dict] = None) -> str:
+ 56            Returns the name of a file.
+ 57
+ 58        load_data(self, file: Union[str, Dict]) -> Dict:
+ 59            Loads a STAC JSON file from a URL or file path and returns a dictionary representation.
+ 60
+ 61        validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
+ 62            Validates a STAC JSON file and returns a dictionary with the validation message.
+ 63
+ 64        recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
+ 65            Validates a STAC JSON file recursively and returns a dictionary with the validation message.
+ 66
+ 67        set_update_message(self) -> str:
+ 68            Sets a message regarding the recommended version of the STAC JSON file standard.
+ 69
+ 70        check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
+ 71            Checks whether the STAC JSON file has links or assets with invalid formats or requests.
+ 72
+ 73        check_error_type(self) -> str:
+ 74            Checks whether the STAC JSON file has an error type.
+ 75
+ 76        check_error_message(self) -> str:
+ 77            Checks whether the STAC JSON file has an error message.
+ 78
+ 79        def check_summaries(self) -> bool:
+ 80            Checks whether the STAC JSON file has summaries.
+ 81
+ 82        check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
+ 83            Checks whether the STAC JSON file has bloated links.
+ 84
+ 85        check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
+ 86            Checks whether the STAC JSON file has bloated metadata.
+ 87
+ 88        check_datetime_null(self) -> bool:
+ 89            Checks whether the STAC JSON file has a null datetime.
+ 90
+ 91        check_unlocated(self) -> bool:
+ 92            Checks whether the STAC JSON file has unlocated items.
+ 93
+ 94        check_geometry_null(self) -> bool:
+ 95            Checks whether the STAC JSON file has a null geometry.
+ 96
+ 97        check_searchable_identifiers(self) -> bool:
+ 98            Checks whether the STAC JSON file has searchable identifiers.
+ 99
+100        check_percent_encoded(self) -> bool:
+101            Checks whether the STAC JSON file has percent-encoded characters.
+102
+103        check_thumbnail(self) -> bool:
+104            Checks whether the STAC JSON file has a thumbnail.
+105
+106        check_links_title_field(self) -> bool:
+107            Checks whether the STAC JSON file has a title field in its links.
+108
+109        check_links_self(self) -> bool:
+110            Checks whether the STAC JSON file has a self link.
+111
+112        check_item_id_file_name(self) -> bool:
+113            Checks whether the filename of an Item conforms to the STAC specification.
+114
+115        check_catalog_file_name(self) -> str:
+116            Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
+117
+118        create_best_practices_dict(self) -> Dict[str, Any]:
+119            Creates a dictionary with best practices recommendations for the STAC JSON file.
+120
+121        create_best_practices_msg(self) -> List[str]:
+122            Creates a message with best practices recommendations for the STAC JSON file.
+123    """
+124
+125    item: Union[str, dict]  # url, file name, or dictionary
+126    config_file: Optional[str] = None
+127    assets: bool = False
+128    links: bool = False
+129    recursive: bool = False
+130    max_depth: Optional[int] = None
+131    assets_open_urls: bool = True
+132    headers: dict = field(default_factory=dict)
+133
+134    def __post_init__(self):
+135        self.data = self.load_data(self.item)
+136        self.message = self.validate_file(self.item)
+137        self.config = self.parse_config(self.config_file)
+138        self.asset_type = (
+139            self.message["asset_type"] if "asset_type" in self.message else ""
+140        )
+141        self.version = self.message["version"] if "version" in self.message else ""
+142        self.validator_version = importlib.metadata.distribution(
+143            "stac-validator"
+144        ).version
+145        self.validate_all = self.recursive_validation(self.item)
+146        self.valid_stac = self.message["valid_stac"]
+147        self.error_type = self.check_error_type()
+148        self.error_msg = self.check_error_message()
+149        self.invalid_asset_format = (
+150            self.check_links_assets(10, "assets", "format") if self.assets else None
+151        )
+152        self.invalid_asset_request = (
+153            self.check_links_assets(10, "assets", "request") if self.assets else None
+154        )
+155        self.invalid_link_format = (
+156            self.check_links_assets(10, "links", "format") if self.links else None
+157        )
+158        self.invalid_link_request = (
+159            self.check_links_assets(10, "links", "request") if self.links else None
+160        )
+161        self.schema = self.message["schema"] if "schema" in self.message else []
+162        self.object_id = self.data["id"] if "id" in self.data else ""
+163        self.file_name = self.get_asset_name(self.item)
+164        self.best_practices_msg = self.create_best_practices_msg()
+165
+166    @staticmethod
+167    def parse_config(config_file: Optional[str] = None) -> Dict:
+168        """Parse the configuration file for STAC checks.
+169
+170        The method first looks for a file path specified in the `STAC_CHECK_CONFIG`
+171        environment variable. If the variable is defined, the method loads the
+172        YAML configuration file located at that path. Otherwise, it loads the default
+173        configuration file packaged with the `stac-check` module.
+174
+175        If `config_file` is specified, the method also loads the YAML configuration
+176        file located at that path and merges its contents with the default or
+177        environment-based configuration.
+178
+179        Args:
+180            config_file (str): The path to the YAML configuration file.
+181
+182        Returns:
+183            A dictionary containing the parsed configuration values.
+184
+185        Raises:
+186            IOError: If `config_file` is specified but cannot be read.
+187            yaml.YAMLError: If any YAML syntax errors occur while parsing the
+188                configuration file(s).
+189        """
+190        default_config_file = os.getenv("STAC_CHECK_CONFIG")
+191        if default_config_file:
+192            with open(default_config_file) as f:
+193                default_config = yaml.load(f, Loader=yaml.FullLoader)
+194        else:
+195            with importlib.resources.open_text(
+196                "stac_check", "stac-check.config.yml"
+197            ) as f:
+198                default_config = yaml.load(f, Loader=yaml.FullLoader)
+199        if config_file:
+200            with open(config_file) as f:
+201                config = yaml.load(f, Loader=yaml.FullLoader)
+202            default_config.update(config)
+203
+204        return default_config
+205
+206    def get_asset_name(self, file: Union[str, Dict] = None) -> str:
+207        """Extracts the name of an asset from its file path or from a STAC item asset dictionary.
+208
+209        Args:
+210            file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the
+211                asset as specified in a STAC item's `assets` property.
+212
+213        Returns:
+214            A string containing the name of the asset.
+215
+216        Raises:
+217            TypeError: If the input `file` is not a string or a dictionary.
+218        """
+219        if isinstance(file, str):
+220            return os.path.basename(file).split(".")[0]
+221        else:
+222            return file["id"]
+223
+224    def load_data(self, file: Union[str, Dict]) -> Dict:
+225        """Loads JSON data from a file or URL.
+226
+227        Args:
+228            file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.
+229
+230        Returns:
+231            A dictionary containing the loaded JSON data.
+232
+233        Raises:
+234            TypeError: If the input `file` is not a string or dictionary.
+235            ValueError: If `file` is a string that doesn't represent a valid URL or file path.
+236            requests.exceptions.RequestException: If there is an error making a request to a URL.
+237            JSONDecodeError: If the JSON data cannot be decoded.
+238            FileNotFoundError: If the specified file cannot be found.
+239        """
+240
+241        if isinstance(file, str):
+242            if is_valid_url(file):
+243                resp = requests.get(file, headers=self.headers)
+244                data = resp.json()
+245            else:
+246                with open(file) as json_file:
+247                    data = json.load(json_file)
+248            return data
+249        else:
+250            return file
+251
+252    def validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
+253        """Validates the given file path or STAC dictionary against the validation schema.
+254
+255        Args:
+256            file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC
+257                item.
+258
+259        Returns:
+260            A dictionary containing the results of the validation, including the status of the validation and any errors
+261            encountered.
+262
+263        Raises:
+264            ValueError: If `file` is not a valid file path or STAC dictionary.
+265        """
+266        if isinstance(file, str):
+267            stac = StacValidate(
+268                file,
+269                links=self.links,
+270                assets=self.assets,
+271                assets_open_urls=self.assets_open_urls,
+272                headers=self.headers,
+273            )
+274            stac.run()
+275        elif isinstance(file, dict):
+276            stac = StacValidate(
+277                assets_open_urls=self.assets_open_urls, headers=self.headers
+278            )
+279            stac.validate_dict(file)
+280        else:
+281            raise ValueError("Input must be a file path or STAC dictionary.")
+282        return stac.message[0]
+283
+284    def recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
+285        """Recursively validate a STAC item or catalog file and its child items.
+286
+287        Args:
+288            file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a
+289                dictionary representing the STAC item or catalog.
+290
+291        Returns:
+292            A string containing the validation message.
+293
+294        Raises:
+295            TypeError: If the input `file` is not a string or a dictionary.
+296        """
+297        if self.recursive:
+298            if isinstance(file, str):
+299                stac = StacValidate(
+300                    file,
+301                    recursive=True,
+302                    max_depth=self.max_depth,
+303                    assets_open_urls=self.assets_open_urls,
+304                    headers=self.headers,
+305                )
+306                stac.run()
+307            else:
+308                stac = StacValidate(
+309                    recursive=True,
+310                    max_depth=self.max_depth,
+311                    assets_open_urls=self.assets_open_urls,
+312                    headers=self.headers,
+313                )
+314                stac.validate_dict(file)
+315            return stac.message
+316        else:
+317            return "Recursive validation is disabled."
+318
+319    def set_update_message(self) -> str:
+320        """Returns a message for users to update their STAC version.
+321
+322        Returns:
+323            A string containing a message for users to update their STAC version.
+324        """
+325        if self.version != "1.0.0":
+326            return f"Please upgrade from version {self.version} to version 1.0.0!"
+327        else:
+328            return "Thanks for using STAC version 1.0.0!"
+329
+330    def check_links_assets(
+331        self, num_links: int, url_type: str, format_type: str
+332    ) -> List[str]:
+333        """Checks the links and assets in the STAC catalog and returns a list of invalid links of a specified type and format.
+334
+335        Args:
+336            num_links (int): The maximum number of invalid links to return.
+337            url_type (str): The type of URL to check, which can be either 'self' or 'external'.
+338            format_type (str): The format of the URL to check, which can be either 'html' or 'json'.
+339
+340        Returns:
+341            A list of invalid links of the specified type and format. If there are no invalid links, an empty list is returned.
+342        """
+343        links = []
+344        if f"{url_type}_validated" in self.message:
+345            for invalid_request_url in self.message[f"{url_type}_validated"][
+346                f"{format_type}_invalid"
+347            ]:
+348                if invalid_request_url not in links and "http" in invalid_request_url:
+349                    links.append(invalid_request_url)
+350                num_links = num_links - 1
+351                if num_links == 0:
+352                    return links
+353        return links
+354
+355    def check_error_type(self) -> str:
+356        """Returns the error type of a STAC validation if it exists in the validation message,
+357        and an empty string otherwise.
+358
+359        Returns:
+360            str: A string containing the error type of a STAC validation if it exists in the validation message, and an
+361            empty string otherwise.
+362        """
+363        if "error_type" in self.message:
+364            return self.message["error_type"]
+365        else:
+366            return ""
+367
+368    def check_error_message(self) -> str:
+369        """Checks whether the `message` attribute contains an `error_message` field.
+370
+371        Returns:
+372            A string containing the value of the `error_message` field, or an empty string if the field is not present.
+373        """
+374        if "error_message" in self.message:
+375            return self.message["error_message"]
+376        else:
+377            return ""
+378
+379    def check_summaries(self) -> bool:
+380        """Check if a Collection asset has a "summaries" property.
+381
+382        Returns:
+383            A boolean indicating whether the Collection asset has a "summaries" property.
+384        """
+385        if self.asset_type == "COLLECTION":
+386            return "summaries" in self.data
+387        else:
+388            return False
+389
+390    def check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
+391        """Checks if the number of links in the STAC data exceeds a certain maximum.
+392
+393        Args:
+394            max_links (Optional[int]): The maximum number of links that the STAC data is allowed to have. Default is 20.
+395
+396        Returns:
+397            bool: A boolean indicating if the number of links in the STAC data exceeds the specified maximum.
+398        """
+399        if "links" in self.data:
+400            return len(self.data["links"]) > max_links
+401        else:
+402            return False
+403
+404    def check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
+405        """Checks whether a STAC item's metadata contains too many properties.
+406
+407        Args:
+408            max_properties (int, optional): The maximum number of properties that the metadata can contain before it is
+409                considered too bloated. Defaults to 20.
+410
+411        Returns:
+412            bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by
+413                `max_properties`, False otherwise.
+414        """
+415        if "properties" in self.data:
+416            return len(self.data["properties"].keys()) > max_properties
+417        return False
+418
+419    def check_datetime_null(self) -> bool:
+420        """Checks if the STAC item has a null datetime property.
+421
+422        Returns:
+423            bool: A boolean indicating whether the datetime property is null (True) or not (False).
+424        """
+425        if "properties" in self.data:
+426            if "datetime" in self.data["properties"]:
+427                if self.data["properties"]["datetime"] is None:
+428                    return True
+429        else:
+430            return False
+431        return False
+432
+433    def check_unlocated(self) -> bool:
+434        """Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.
+435
+436        Returns:
+437            bool: True if the STAC item is unlocated, False otherwise.
+438        """
+439        if "geometry" in self.data:
+440            return self.data["geometry"] is None and self.data["bbox"] is not None
+441        else:
+442            return False
+443
+444    def check_geometry_null(self) -> bool:
+445        """Checks if a STAC item has a null geometry property.
+446
+447        Returns:
+448            bool: A boolean indicating whether the geometry property is null (True) or not (False).
+449        """
+450        if "geometry" in self.data:
+451            return self.data["geometry"] is None
+452        else:
+453            return False
+454
+455    def check_searchable_identifiers(self) -> bool:
+456        """Checks if the identifiers of a STAC item are searchable, i.e.,
+457        they only contain lowercase letters, numbers, hyphens, and underscores.
+458
+459        Returns:
+460            bool: True if the identifiers are searchable, False otherwise.
+461        """
+462        if self.asset_type == "ITEM":
+463            for letter in self.object_id:
+464                if (
+465                    letter.islower()
+466                    or letter.isnumeric()
+467                    or letter == "-"
+468                    or letter == "_"
+469                ):
+470                    pass
+471                else:
+472                    return False
+473        return True
+474
+475    def check_percent_encoded(self) -> bool:
+476        """Checks if the identifiers of a STAC item are percent-encoded, i.e.,
+477        they only contain lowercase letters, numbers, hyphens, and underscores.
+478
+479        Returns:
+480            bool: True if the identifiers are percent-encoded, False otherwise.
+481        """
+482        return (
+483            self.asset_type == "ITEM" and "/" in self.object_id or ":" in self.object_id
+484        )
+485
+486    def check_thumbnail(self) -> bool:
+487        """Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format.
+488
+489        Returns:
+490            bool: True if the thumbnail is valid, False otherwise.
+491        """
+492        if "assets" in self.data:
+493            if "thumbnail" in self.data["assets"]:
+494                if "type" in self.data["assets"]["thumbnail"]:
+495                    if (
+496                        "png" in self.data["assets"]["thumbnail"]["type"]
+497                        or "jpeg" in self.data["assets"]["thumbnail"]["type"]
+498                        or "jpg" in self.data["assets"]["thumbnail"]["type"]
+499                        or "webp" in self.data["assets"]["thumbnail"]["type"]
+500                    ):
+501                        return True
+502                    else:
+503                        return False
+504        return True
+505
+506    def check_links_title_field(self) -> bool:
+507        """Checks if all links in a STAC collection or catalog have a 'title' field.
+508        The 'title' field is not required for the 'self' link.
+509
+510        Returns:
+511            bool: True if all links have a 'title' field, False otherwise.
+512        """
+513        if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG":
+514            for link in self.data["links"]:
+515                if "title" not in link and link["rel"] != "self":
+516                    return False
+517        return True
+518
+519    def check_links_self(self) -> bool:
+520        """Checks whether the "self" link is present in the STAC collection or catalog or absent in STAC item.
+521
+522        Returns:
+523            bool: True if the "self" link is present in STAC collection or catalog or absent in STAC item, False otherwise.
+524        """
+525        if self.asset_type == "ITEM":
+526            return True
+527        if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG":
+528            for link in self.data["links"]:
+529                if "self" in link["rel"]:
+530                    return True
+531        return False
+532
+533    def check_item_id_file_name(self) -> bool:
+534        if self.asset_type == "ITEM" and self.object_id != self.file_name:
+535            return False
+536        else:
+537            return True
+538
+539    def check_catalog_file_name(self) -> bool:
+540        """Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
+541
+542        Returns:
+543            bool: True if the filename is valid, False otherwise.
+544        """
+545        if isinstance(self.item, str) and ".json" in self.item:
+546            if self.asset_type == "CATALOG" and "catalog.json" not in self.item:
+547                return False
+548            elif self.asset_type == "COLLECTION" and "collection.json" not in self.item:
+549                return False
+550            return True
+551        else:
+552            return True
+553
+554    def create_best_practices_dict(self) -> Dict:
+555        """Creates a dictionary of best practices violations for the current STAC object. The violations are determined
+556        by a set of configurable linting rules specified in the config file.
+557
+558        Returns:
+559            A dictionary of best practices violations for the current STAC object. The keys in the dictionary correspond
+560            to the linting rules that were violated, and the values are lists of strings containing error messages and
+561            recommendations for how to fix the violations.
+562        """
+563        best_practices_dict = {}
+564        config = self.config["linting"]
+565        max_links = self.config["settings"]["max_links"]
+566        max_properties = self.config["settings"]["max_properties"]
+567
+568        # best practices - item ids should only contain searchable identifiers
+569        if (
+570            self.check_searchable_identifiers() == False
+571            and config["searchable_identifiers"] == True
+572        ):
+573            msg_1 = f"Item name '{self.object_id}' should only contain Searchable identifiers"
+574            msg_2 = "Identifiers should consist of only lowercase characters, numbers, '_', and '-'"
+575            best_practices_dict["searchable_identifiers"] = [msg_1, msg_2]
+576
+577        # best practices - item ids should not contain ':' or '/' characters
+578        if self.check_percent_encoded() and config["percent_encoded"] == True:
+579            msg_1 = f"Item name '{self.object_id}' should not contain ':' or '/'"
+580            msg_2 = "https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#item-ids"
+581            best_practices_dict["percent_encoded"] = [msg_1, msg_2]
+582
+583        # best practices - item ids should match file names
+584        if not self.check_item_id_file_name() and config["item_id_file_name"] == True:
+585            msg_1 = f"Item file names should match their ids: '{self.file_name}' not equal to '{self.object_id}"
+586            best_practices_dict["check_item_id"] = [msg_1]
+587
+588        # best practices - collection and catalog file names should be collection.json and catalog.json
+589        if (
+590            self.check_catalog_file_name() == False
+591            and config["catalog_id_file_name"] == True
+592        ):
+593            msg_1 = f"Object should be called '{self.asset_type.lower()}.json' not '{self.file_name}.json'"
+594            best_practices_dict["check_catalog_id"] = [msg_1]
+595
+596        # best practices - collections should contain summaries
+597        if self.check_summaries() == False and config["check_summaries"] == True:
+598            msg_1 = "A STAC collection should contain a summaries field"
+599            msg_2 = "It is recommended to store information like eo:bands in summaries"
+600            best_practices_dict["check_summaries"] = [msg_1, msg_2]
+601
+602        # best practices - datetime fields should not be set to null
+603        if self.check_datetime_null() and config["null_datetime"] == True:
+604            msg_1 = "Please avoid setting the datetime field to null, many clients search on this field"
+605            best_practices_dict["datetime_null"] = [msg_1]
+606
+607        # best practices - check unlocated items to make sure bbox field is not set
+608        if self.check_unlocated() and config["check_unlocated"] == True:
+609            msg_1 = "Unlocated item. Please avoid setting the bbox field when geometry is set to null"
+610            best_practices_dict["check_unlocated"] = [msg_1]
+611
+612        # best practices - recommend items have a geometry
+613        if self.check_geometry_null() and config["check_geometry"] == True:
+614            msg_1 = "All items should have a geometry field. STAC is not meant for non-spatial data"
+615            best_practices_dict["null_geometry"] = [msg_1]
+616
+617        # check to see if there are too many links
+618        if (
+619            self.check_bloated_links(max_links=max_links)
+620            and config["bloated_links"] == True
+621        ):
+622            msg_1 = f"You have {len(self.data['links'])} links. Please consider using sub-collections or sub-catalogs"
+623            best_practices_dict["bloated_links"] = [msg_1]
+624
+625        # best practices - check for bloated metadata in properties
+626        if (
+627            self.check_bloated_metadata(max_properties=max_properties)
+628            and config["bloated_metadata"] == True
+629        ):
+630            msg_1 = f"You have {len(self.data['properties'])} properties. Please consider using links to avoid bloated metadata"
+631            best_practices_dict["bloated_metadata"] = [msg_1]
+632
+633        # best practices - ensure thumbnail is a small file size ["png", "jpeg", "jpg", "webp"]
+634        if (
+635            not self.check_thumbnail()
+636            and self.asset_type == "ITEM"
+637            and config["check_thumbnail"] == True
+638        ):
+639            msg_1 = "A thumbnail should have a small file size ie. png, jpeg, jpg, webp"
+640            best_practices_dict["check_thumbnail"] = [msg_1]
+641
+642        # best practices - ensure that links in catalogs and collections include a title field
+643        if not self.check_links_title_field() and config["links_title"] == True:
+644            msg_1 = (
+645                "Links in catalogs and collections should always have a 'title' field"
+646            )
+647            best_practices_dict["check_links_title"] = [msg_1]
+648
+649        # best practices - ensure that links in catalogs and collections include self link
+650        if not self.check_links_self() and config["links_self"] == True:
+651            msg_1 = "A link to 'self' in links is strongly recommended"
+652            best_practices_dict["check_links_self"] = [msg_1]
+653
+654        return best_practices_dict
+655
+656    def create_best_practices_msg(self) -> List[str]:
+657        """
+658        Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method.
+659
+660        Returns:
+661            A list of strings, where each string contains a best practice message. Each message starts with the
+662            'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented
+663            with four spaces, and there is an empty string between each message for readability.
+664        """
+665        best_practices = list()
+666        base_string = "STAC Best Practices: "
+667        best_practices.append(base_string)
+668
+669        for _, v in self.create_best_practices_dict().items():
+670            for value in v:
+671                best_practices.extend(["    " + value])
+672            best_practices.extend([""])
+673
+674        return best_practices
+
+ + +
+
+ +
+
@dataclass
+ + class + Linter: + + + +
+ +
 18@dataclass
+ 19class Linter:
+ 20    """A class for linting STAC JSON files and generating validation messages.
+ 21
+ 22    Args:
+ 23        item (Union[str, dict]): A URL, file name, or dictionary representing a STAC JSON file.
+ 24        config_file (Optional[str], optional): A path to a YAML configuration file. Defaults to None.
+ 25        assets (bool, optional): A boolean value indicating whether to validate assets. Defaults to False.
+ 26        links (bool, optional): A boolean value indicating whether to validate links. Defaults to False.
+ 27        recursive (bool, optional): A boolean value indicating whether to perform recursive validation. Defaults to False.
+ 28        max_depth (Optional[int], optional): An optional integer indicating the maximum depth to validate recursively. Defaults to None.
+ 29        assets_open_urls (bool): Whether to open assets URLs when validating assets. Defaults to True.
+ 30        headers (dict): HTTP headers to include in the requests.
+ 31
+ 32    Attributes:
+ 33        data (dict): A dictionary representing the STAC JSON file.
+ 34        message (dict): A dictionary containing the validation message for the STAC JSON file.
+ 35        config (dict): A dictionary containing the configuration settings.
+ 36        asset_type (str): A string representing the asset type, if one is specified.
+ 37        version (str): A string representing the version of the STAC standard used in the STAC JSON file.
+ 38        validator_version (str): A string representing the version of the STAC validator used to validate the STAC JSON file.
+ 39        validate_all (dict): A dictionary containing the validation message for all STAC JSON files found recursively, if recursive validation was performed.
+ 40        valid_stac (bool): A boolean value indicating whether the STAC JSON file is valid.
+ 41        error_type (str): A string representing the type of error in the STAC JSON file, if one exists.
+ 42        error_msg (str): A string representing the error message in the STAC JSON file, if one exists.
+ 43        invalid_asset_format (List[str]): A list of URLs with invalid asset formats, if assets were validated.
+ 44        invalid_asset_request (List[str]): A list of URLs with invalid asset requests, if assets were validated.
+ 45        invalid_link_format (List[str]): A list of URLs with invalid link formats, if links were validated.
+ 46        invalid_link_request (List[str]): A list of URLs with invalid link requests, if links were validated.
+ 47        schema (List[str]): A list of the STAC JSON file's JSON schema files.
+ 48        object_id (str): A string representing the STAC JSON file's ID.
+ 49        file_name (str): A string representing the name of the file containing the STAC JSON data.
+ 50        best_practices_msg (str): A string representing best practices messages for the STAC JSON file.
+ 51
+ 52    Methods:
+ 53        parse_config(config_file: Optional[str] = None) -> Dict:
+ 54            Parses a YAML configuration file and returns a dictionary with the configuration settings.
+ 55
+ 56        def get_asset_name(self, file: Union[str, Dict] = None) -> str:
+ 57            Returns the name of a file.
+ 58
+ 59        load_data(self, file: Union[str, Dict]) -> Dict:
+ 60            Loads a STAC JSON file from a URL or file path and returns a dictionary representation.
+ 61
+ 62        validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
+ 63            Validates a STAC JSON file and returns a dictionary with the validation message.
+ 64
+ 65        recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
+ 66            Validates a STAC JSON file recursively and returns a dictionary with the validation message.
+ 67
+ 68        set_update_message(self) -> str:
+ 69            Sets a message regarding the recommended version of the STAC JSON file standard.
+ 70
+ 71        check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
+ 72            Checks whether the STAC JSON file has links or assets with invalid formats or requests.
+ 73
+ 74        check_error_type(self) -> str:
+ 75            Checks whether the STAC JSON file has an error type.
+ 76
+ 77        check_error_message(self) -> str:
+ 78            Checks whether the STAC JSON file has an error message.
+ 79
+ 80        def check_summaries(self) -> bool:
+ 81            Checks whether the STAC JSON file has summaries.
+ 82
+ 83        check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
+ 84            Checks whether the STAC JSON file has bloated links.
+ 85
+ 86        check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
+ 87            Checks whether the STAC JSON file has bloated metadata.
+ 88
+ 89        check_datetime_null(self) -> bool:
+ 90            Checks whether the STAC JSON file has a null datetime.
+ 91
+ 92        check_unlocated(self) -> bool:
+ 93            Checks whether the STAC JSON file has unlocated items.
+ 94
+ 95        check_geometry_null(self) -> bool:
+ 96            Checks whether the STAC JSON file has a null geometry.
+ 97
+ 98        check_searchable_identifiers(self) -> bool:
+ 99            Checks whether the STAC JSON file has searchable identifiers.
+100
+101        check_percent_encoded(self) -> bool:
+102            Checks whether the STAC JSON file has percent-encoded characters.
+103
+104        check_thumbnail(self) -> bool:
+105            Checks whether the STAC JSON file has a thumbnail.
+106
+107        check_links_title_field(self) -> bool:
+108            Checks whether the STAC JSON file has a title field in its links.
+109
+110        check_links_self(self) -> bool:
+111            Checks whether the STAC JSON file has a self link.
+112
+113        check_item_id_file_name(self) -> bool:
+114            Checks whether the filename of an Item conforms to the STAC specification.
+115
+116        check_catalog_file_name(self) -> str:
+117            Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
+118
+119        create_best_practices_dict(self) -> Dict[str, Any]:
+120            Creates a dictionary with best practices recommendations for the STAC JSON file.
+121
+122        create_best_practices_msg(self) -> List[str]:
+123            Creates a message with best practices recommendations for the STAC JSON file.
+124    """
+125
+126    item: Union[str, dict]  # url, file name, or dictionary
+127    config_file: Optional[str] = None
+128    assets: bool = False
+129    links: bool = False
+130    recursive: bool = False
+131    max_depth: Optional[int] = None
+132    assets_open_urls: bool = True
+133    headers: dict = field(default_factory=dict)
+134
+135    def __post_init__(self):
+136        self.data = self.load_data(self.item)
+137        self.message = self.validate_file(self.item)
+138        self.config = self.parse_config(self.config_file)
+139        self.asset_type = (
+140            self.message["asset_type"] if "asset_type" in self.message else ""
+141        )
+142        self.version = self.message["version"] if "version" in self.message else ""
+143        self.validator_version = importlib.metadata.distribution(
+144            "stac-validator"
+145        ).version
+146        self.validate_all = self.recursive_validation(self.item)
+147        self.valid_stac = self.message["valid_stac"]
+148        self.error_type = self.check_error_type()
+149        self.error_msg = self.check_error_message()
+150        self.invalid_asset_format = (
+151            self.check_links_assets(10, "assets", "format") if self.assets else None
+152        )
+153        self.invalid_asset_request = (
+154            self.check_links_assets(10, "assets", "request") if self.assets else None
+155        )
+156        self.invalid_link_format = (
+157            self.check_links_assets(10, "links", "format") if self.links else None
+158        )
+159        self.invalid_link_request = (
+160            self.check_links_assets(10, "links", "request") if self.links else None
+161        )
+162        self.schema = self.message["schema"] if "schema" in self.message else []
+163        self.object_id = self.data["id"] if "id" in self.data else ""
+164        self.file_name = self.get_asset_name(self.item)
+165        self.best_practices_msg = self.create_best_practices_msg()
+166
+167    @staticmethod
+168    def parse_config(config_file: Optional[str] = None) -> Dict:
+169        """Parse the configuration file for STAC checks.
+170
+171        The method first looks for a file path specified in the `STAC_CHECK_CONFIG`
+172        environment variable. If the variable is defined, the method loads the
+173        YAML configuration file located at that path. Otherwise, it loads the default
+174        configuration file packaged with the `stac-check` module.
+175
+176        If `config_file` is specified, the method also loads the YAML configuration
+177        file located at that path and merges its contents with the default or
+178        environment-based configuration.
+179
+180        Args:
+181            config_file (str): The path to the YAML configuration file.
+182
+183        Returns:
+184            A dictionary containing the parsed configuration values.
+185
+186        Raises:
+187            IOError: If `config_file` is specified but cannot be read.
+188            yaml.YAMLError: If any YAML syntax errors occur while parsing the
+189                configuration file(s).
+190        """
+191        default_config_file = os.getenv("STAC_CHECK_CONFIG")
+192        if default_config_file:
+193            with open(default_config_file) as f:
+194                default_config = yaml.load(f, Loader=yaml.FullLoader)
+195        else:
+196            with importlib.resources.open_text(
+197                "stac_check", "stac-check.config.yml"
+198            ) as f:
+199                default_config = yaml.load(f, Loader=yaml.FullLoader)
+200        if config_file:
+201            with open(config_file) as f:
+202                config = yaml.load(f, Loader=yaml.FullLoader)
+203            default_config.update(config)
+204
+205        return default_config
+206
+207    def get_asset_name(self, file: Union[str, Dict] = None) -> str:
+208        """Extracts the name of an asset from its file path or from a STAC item asset dictionary.
+209
+210        Args:
+211            file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the
+212                asset as specified in a STAC item's `assets` property.
+213
+214        Returns:
+215            A string containing the name of the asset.
+216
+217        Raises:
+218            TypeError: If the input `file` is not a string or a dictionary.
+219        """
+220        if isinstance(file, str):
+221            return os.path.basename(file).split(".")[0]
+222        else:
+223            return file["id"]
+224
+225    def load_data(self, file: Union[str, Dict]) -> Dict:
+226        """Loads JSON data from a file or URL.
+227
+228        Args:
+229            file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.
+230
+231        Returns:
+232            A dictionary containing the loaded JSON data.
+233
+234        Raises:
+235            TypeError: If the input `file` is not a string or dictionary.
+236            ValueError: If `file` is a string that doesn't represent a valid URL or file path.
+237            requests.exceptions.RequestException: If there is an error making a request to a URL.
+238            JSONDecodeError: If the JSON data cannot be decoded.
+239            FileNotFoundError: If the specified file cannot be found.
+240        """
+241
+242        if isinstance(file, str):
+243            if is_valid_url(file):
+244                resp = requests.get(file, headers=self.headers)
+245                data = resp.json()
+246            else:
+247                with open(file) as json_file:
+248                    data = json.load(json_file)
+249            return data
+250        else:
+251            return file
+252
+253    def validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
+254        """Validates the given file path or STAC dictionary against the validation schema.
+255
+256        Args:
+257            file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC
+258                item.
+259
+260        Returns:
+261            A dictionary containing the results of the validation, including the status of the validation and any errors
+262            encountered.
+263
+264        Raises:
+265            ValueError: If `file` is not a valid file path or STAC dictionary.
+266        """
+267        if isinstance(file, str):
+268            stac = StacValidate(
+269                file,
+270                links=self.links,
+271                assets=self.assets,
+272                assets_open_urls=self.assets_open_urls,
+273                headers=self.headers,
+274            )
+275            stac.run()
+276        elif isinstance(file, dict):
+277            stac = StacValidate(
+278                assets_open_urls=self.assets_open_urls, headers=self.headers
+279            )
+280            stac.validate_dict(file)
+281        else:
+282            raise ValueError("Input must be a file path or STAC dictionary.")
+283        return stac.message[0]
+284
+285    def recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
+286        """Recursively validate a STAC item or catalog file and its child items.
+287
+288        Args:
+289            file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a
+290                dictionary representing the STAC item or catalog.
+291
+292        Returns:
+293            A string containing the validation message.
+294
+295        Raises:
+296            TypeError: If the input `file` is not a string or a dictionary.
+297        """
+298        if self.recursive:
+299            if isinstance(file, str):
+300                stac = StacValidate(
+301                    file,
+302                    recursive=True,
+303                    max_depth=self.max_depth,
+304                    assets_open_urls=self.assets_open_urls,
+305                    headers=self.headers,
+306                )
+307                stac.run()
+308            else:
+309                stac = StacValidate(
+310                    recursive=True,
+311                    max_depth=self.max_depth,
+312                    assets_open_urls=self.assets_open_urls,
+313                    headers=self.headers,
+314                )
+315                stac.validate_dict(file)
+316            return stac.message
+317        else:
+318            return "Recursive validation is disabled."
+319
+320    def set_update_message(self) -> str:
+321        """Returns a message for users to update their STAC version.
+322
+323        Returns:
+324            A string containing a message for users to update their STAC version.
+325        """
+326        if self.version != "1.0.0":
+327            return f"Please upgrade from version {self.version} to version 1.0.0!"
+328        else:
+329            return "Thanks for using STAC version 1.0.0!"
+330
+331    def check_links_assets(
+332        self, num_links: int, url_type: str, format_type: str
+333    ) -> List[str]:
+334        """Checks the links and assets in the STAC catalog and returns a list of invalid links of a specified type and format.
+335
+336        Args:
+337            num_links (int): The maximum number of invalid links to return.
+338            url_type (str): The type of URL to check, which can be either 'self' or 'external'.
+339            format_type (str): The format of the URL to check, which can be either 'html' or 'json'.
+340
+341        Returns:
+342            A list of invalid links of the specified type and format. If there are no invalid links, an empty list is returned.
+343        """
+344        links = []
+345        if f"{url_type}_validated" in self.message:
+346            for invalid_request_url in self.message[f"{url_type}_validated"][
+347                f"{format_type}_invalid"
+348            ]:
+349                if invalid_request_url not in links and "http" in invalid_request_url:
+350                    links.append(invalid_request_url)
+351                num_links = num_links - 1
+352                if num_links == 0:
+353                    return links
+354        return links
+355
+356    def check_error_type(self) -> str:
+357        """Returns the error type of a STAC validation if it exists in the validation message,
+358        and an empty string otherwise.
+359
+360        Returns:
+361            str: A string containing the error type of a STAC validation if it exists in the validation message, and an
+362            empty string otherwise.
+363        """
+364        if "error_type" in self.message:
+365            return self.message["error_type"]
+366        else:
+367            return ""
+368
+369    def check_error_message(self) -> str:
+370        """Checks whether the `message` attribute contains an `error_message` field.
+371
+372        Returns:
+373            A string containing the value of the `error_message` field, or an empty string if the field is not present.
+374        """
+375        if "error_message" in self.message:
+376            return self.message["error_message"]
+377        else:
+378            return ""
+379
+380    def check_summaries(self) -> bool:
+381        """Check if a Collection asset has a "summaries" property.
+382
+383        Returns:
+384            A boolean indicating whether the Collection asset has a "summaries" property.
+385        """
+386        if self.asset_type == "COLLECTION":
+387            return "summaries" in self.data
+388        else:
+389            return False
+390
+391    def check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
+392        """Checks if the number of links in the STAC data exceeds a certain maximum.
+393
+394        Args:
+395            max_links (Optional[int]): The maximum number of links that the STAC data is allowed to have. Default is 20.
+396
+397        Returns:
+398            bool: A boolean indicating if the number of links in the STAC data exceeds the specified maximum.
+399        """
+400        if "links" in self.data:
+401            return len(self.data["links"]) > max_links
+402        else:
+403            return False
+404
+405    def check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
+406        """Checks whether a STAC item's metadata contains too many properties.
+407
+408        Args:
+409            max_properties (int, optional): The maximum number of properties that the metadata can contain before it is
+410                considered too bloated. Defaults to 20.
+411
+412        Returns:
+413            bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by
+414                `max_properties`, False otherwise.
+415        """
+416        if "properties" in self.data:
+417            return len(self.data["properties"].keys()) > max_properties
+418        return False
+419
+420    def check_datetime_null(self) -> bool:
+421        """Checks if the STAC item has a null datetime property.
+422
+423        Returns:
+424            bool: A boolean indicating whether the datetime property is null (True) or not (False).
+425        """
+426        if "properties" in self.data:
+427            if "datetime" in self.data["properties"]:
+428                if self.data["properties"]["datetime"] is None:
+429                    return True
+430        else:
+431            return False
+432        return False
+433
+434    def check_unlocated(self) -> bool:
+435        """Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.
+436
+437        Returns:
+438            bool: True if the STAC item is unlocated, False otherwise.
+439        """
+440        if "geometry" in self.data:
+441            return self.data["geometry"] is None and self.data["bbox"] is not None
+442        else:
+443            return False
+444
+445    def check_geometry_null(self) -> bool:
+446        """Checks if a STAC item has a null geometry property.
+447
+448        Returns:
+449            bool: A boolean indicating whether the geometry property is null (True) or not (False).
+450        """
+451        if "geometry" in self.data:
+452            return self.data["geometry"] is None
+453        else:
+454            return False
+455
+456    def check_searchable_identifiers(self) -> bool:
+457        """Checks if the identifiers of a STAC item are searchable, i.e.,
+458        they only contain lowercase letters, numbers, hyphens, and underscores.
+459
+460        Returns:
+461            bool: True if the identifiers are searchable, False otherwise.
+462        """
+463        if self.asset_type == "ITEM":
+464            for letter in self.object_id:
+465                if (
+466                    letter.islower()
+467                    or letter.isnumeric()
+468                    or letter == "-"
+469                    or letter == "_"
+470                ):
+471                    pass
+472                else:
+473                    return False
+474        return True
+475
+476    def check_percent_encoded(self) -> bool:
+477        """Checks if the identifiers of a STAC item are percent-encoded, i.e.,
+478        they only contain lowercase letters, numbers, hyphens, and underscores.
+479
+480        Returns:
+481            bool: True if the identifiers are percent-encoded, False otherwise.
+482        """
+483        return (
+484            self.asset_type == "ITEM" and "/" in self.object_id or ":" in self.object_id
+485        )
+486
+487    def check_thumbnail(self) -> bool:
+488        """Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format.
+489
+490        Returns:
+491            bool: True if the thumbnail is valid, False otherwise.
+492        """
+493        if "assets" in self.data:
+494            if "thumbnail" in self.data["assets"]:
+495                if "type" in self.data["assets"]["thumbnail"]:
+496                    if (
+497                        "png" in self.data["assets"]["thumbnail"]["type"]
+498                        or "jpeg" in self.data["assets"]["thumbnail"]["type"]
+499                        or "jpg" in self.data["assets"]["thumbnail"]["type"]
+500                        or "webp" in self.data["assets"]["thumbnail"]["type"]
+501                    ):
+502                        return True
+503                    else:
+504                        return False
+505        return True
+506
+507    def check_links_title_field(self) -> bool:
+508        """Checks if all links in a STAC collection or catalog have a 'title' field.
+509        The 'title' field is not required for the 'self' link.
+510
+511        Returns:
+512            bool: True if all links have a 'title' field, False otherwise.
+513        """
+514        if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG":
+515            for link in self.data["links"]:
+516                if "title" not in link and link["rel"] != "self":
+517                    return False
+518        return True
+519
+520    def check_links_self(self) -> bool:
+521        """Checks whether the "self" link is present in the STAC collection or catalog or absent in STAC item.
+522
+523        Returns:
+524            bool: True if the "self" link is present in STAC collection or catalog or absent in STAC item, False otherwise.
+525        """
+526        if self.asset_type == "ITEM":
+527            return True
+528        if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG":
+529            for link in self.data["links"]:
+530                if "self" in link["rel"]:
+531                    return True
+532        return False
+533
+534    def check_item_id_file_name(self) -> bool:
+535        if self.asset_type == "ITEM" and self.object_id != self.file_name:
+536            return False
+537        else:
+538            return True
+539
+540    def check_catalog_file_name(self) -> bool:
+541        """Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
+542
+543        Returns:
+544            bool: True if the filename is valid, False otherwise.
+545        """
+546        if isinstance(self.item, str) and ".json" in self.item:
+547            if self.asset_type == "CATALOG" and "catalog.json" not in self.item:
+548                return False
+549            elif self.asset_type == "COLLECTION" and "collection.json" not in self.item:
+550                return False
+551            return True
+552        else:
+553            return True
+554
+555    def create_best_practices_dict(self) -> Dict:
+556        """Creates a dictionary of best practices violations for the current STAC object. The violations are determined
+557        by a set of configurable linting rules specified in the config file.
+558
+559        Returns:
+560            A dictionary of best practices violations for the current STAC object. The keys in the dictionary correspond
+561            to the linting rules that were violated, and the values are lists of strings containing error messages and
+562            recommendations for how to fix the violations.
+563        """
+564        best_practices_dict = {}
+565        config = self.config["linting"]
+566        max_links = self.config["settings"]["max_links"]
+567        max_properties = self.config["settings"]["max_properties"]
+568
+569        # best practices - item ids should only contain searchable identifiers
+570        if (
+571            self.check_searchable_identifiers() == False
+572            and config["searchable_identifiers"] == True
+573        ):
+574            msg_1 = f"Item name '{self.object_id}' should only contain Searchable identifiers"
+575            msg_2 = "Identifiers should consist of only lowercase characters, numbers, '_', and '-'"
+576            best_practices_dict["searchable_identifiers"] = [msg_1, msg_2]
+577
+578        # best practices - item ids should not contain ':' or '/' characters
+579        if self.check_percent_encoded() and config["percent_encoded"] == True:
+580            msg_1 = f"Item name '{self.object_id}' should not contain ':' or '/'"
+581            msg_2 = "https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#item-ids"
+582            best_practices_dict["percent_encoded"] = [msg_1, msg_2]
+583
+584        # best practices - item ids should match file names
+585        if not self.check_item_id_file_name() and config["item_id_file_name"] == True:
+586            msg_1 = f"Item file names should match their ids: '{self.file_name}' not equal to '{self.object_id}"
+587            best_practices_dict["check_item_id"] = [msg_1]
+588
+589        # best practices - collection and catalog file names should be collection.json and catalog.json
+590        if (
+591            self.check_catalog_file_name() == False
+592            and config["catalog_id_file_name"] == True
+593        ):
+594            msg_1 = f"Object should be called '{self.asset_type.lower()}.json' not '{self.file_name}.json'"
+595            best_practices_dict["check_catalog_id"] = [msg_1]
+596
+597        # best practices - collections should contain summaries
+598        if self.check_summaries() == False and config["check_summaries"] == True:
+599            msg_1 = "A STAC collection should contain a summaries field"
+600            msg_2 = "It is recommended to store information like eo:bands in summaries"
+601            best_practices_dict["check_summaries"] = [msg_1, msg_2]
+602
+603        # best practices - datetime fields should not be set to null
+604        if self.check_datetime_null() and config["null_datetime"] == True:
+605            msg_1 = "Please avoid setting the datetime field to null, many clients search on this field"
+606            best_practices_dict["datetime_null"] = [msg_1]
+607
+608        # best practices - check unlocated items to make sure bbox field is not set
+609        if self.check_unlocated() and config["check_unlocated"] == True:
+610            msg_1 = "Unlocated item. Please avoid setting the bbox field when geometry is set to null"
+611            best_practices_dict["check_unlocated"] = [msg_1]
+612
+613        # best practices - recommend items have a geometry
+614        if self.check_geometry_null() and config["check_geometry"] == True:
+615            msg_1 = "All items should have a geometry field. STAC is not meant for non-spatial data"
+616            best_practices_dict["null_geometry"] = [msg_1]
+617
+618        # check to see if there are too many links
+619        if (
+620            self.check_bloated_links(max_links=max_links)
+621            and config["bloated_links"] == True
+622        ):
+623            msg_1 = f"You have {len(self.data['links'])} links. Please consider using sub-collections or sub-catalogs"
+624            best_practices_dict["bloated_links"] = [msg_1]
+625
+626        # best practices - check for bloated metadata in properties
+627        if (
+628            self.check_bloated_metadata(max_properties=max_properties)
+629            and config["bloated_metadata"] == True
+630        ):
+631            msg_1 = f"You have {len(self.data['properties'])} properties. Please consider using links to avoid bloated metadata"
+632            best_practices_dict["bloated_metadata"] = [msg_1]
+633
+634        # best practices - ensure thumbnail is a small file size ["png", "jpeg", "jpg", "webp"]
+635        if (
+636            not self.check_thumbnail()
+637            and self.asset_type == "ITEM"
+638            and config["check_thumbnail"] == True
+639        ):
+640            msg_1 = "A thumbnail should have a small file size ie. png, jpeg, jpg, webp"
+641            best_practices_dict["check_thumbnail"] = [msg_1]
+642
+643        # best practices - ensure that links in catalogs and collections include a title field
+644        if not self.check_links_title_field() and config["links_title"] == True:
+645            msg_1 = (
+646                "Links in catalogs and collections should always have a 'title' field"
+647            )
+648            best_practices_dict["check_links_title"] = [msg_1]
+649
+650        # best practices - ensure that links in catalogs and collections include self link
+651        if not self.check_links_self() and config["links_self"] == True:
+652            msg_1 = "A link to 'self' in links is strongly recommended"
+653            best_practices_dict["check_links_self"] = [msg_1]
+654
+655        return best_practices_dict
+656
+657    def create_best_practices_msg(self) -> List[str]:
+658        """
+659        Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method.
+660
+661        Returns:
+662            A list of strings, where each string contains a best practice message. Each message starts with the
+663            'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented
+664            with four spaces, and there is an empty string between each message for readability.
+665        """
+666        best_practices = list()
+667        base_string = "STAC Best Practices: "
+668        best_practices.append(base_string)
+669
+670        for _, v in self.create_best_practices_dict().items():
+671            for value in v:
+672                best_practices.extend(["    " + value])
+673            best_practices.extend([""])
+674
+675        return best_practices
+
+ + +

A class for linting STAC JSON files and generating validation messages.

+ +

Args: + item (Union[str, dict]): A URL, file name, or dictionary representing a STAC JSON file. + config_file (Optional[str], optional): A path to a YAML configuration file. Defaults to None. + assets (bool, optional): A boolean value indicating whether to validate assets. Defaults to False. + links (bool, optional): A boolean value indicating whether to validate links. Defaults to False. + recursive (bool, optional): A boolean value indicating whether to perform recursive validation. Defaults to False. + max_depth (Optional[int], optional): An optional integer indicating the maximum depth to validate recursively. Defaults to None. + assets_open_urls (bool): Whether to open assets URLs when validating assets. Defaults to True. + headers (dict): HTTP headers to include in the requests.

+ +

Attributes: + data (dict): A dictionary representing the STAC JSON file. + message (dict): A dictionary containing the validation message for the STAC JSON file. + config (dict): A dictionary containing the configuration settings. + asset_type (str): A string representing the asset type, if one is specified. + version (str): A string representing the version of the STAC standard used in the STAC JSON file. + validator_version (str): A string representing the version of the STAC validator used to validate the STAC JSON file. + validate_all (dict): A dictionary containing the validation message for all STAC JSON files found recursively, if recursive validation was performed. + valid_stac (bool): A boolean value indicating whether the STAC JSON file is valid. + error_type (str): A string representing the type of error in the STAC JSON file, if one exists. + error_msg (str): A string representing the error message in the STAC JSON file, if one exists. + invalid_asset_format (List[str]): A list of URLs with invalid asset formats, if assets were validated. + invalid_asset_request (List[str]): A list of URLs with invalid asset requests, if assets were validated. + invalid_link_format (List[str]): A list of URLs with invalid link formats, if links were validated. + invalid_link_request (List[str]): A list of URLs with invalid link requests, if links were validated. + schema (List[str]): A list of the STAC JSON file's JSON schema files. + object_id (str): A string representing the STAC JSON file's ID. + file_name (str): A string representing the name of the file containing the STAC JSON data. + best_practices_msg (str): A string representing best practices messages for the STAC JSON file.

+ +

Methods: + parse_config(config_file: Optional[str] = None) -> Dict: + Parses a YAML configuration file and returns a dictionary with the configuration settings.

+ +
def get_asset_name(self, file: Union[str, Dict] = None) -> str:
+    Returns the name of a file.
+
+load_data(self, file: Union[str, Dict]) -> Dict:
+    Loads a STAC JSON file from a URL or file path and returns a dictionary representation.
+
+validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
+    Validates a STAC JSON file and returns a dictionary with the validation message.
+
+recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
+    Validates a STAC JSON file recursively and returns a dictionary with the validation message.
+
+set_update_message(self) -> str:
+    Sets a message regarding the recommended version of the STAC JSON file standard.
+
+check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
+    Checks whether the STAC JSON file has links or assets with invalid formats or requests.
+
+check_error_type(self) -> str:
+    Checks whether the STAC JSON file has an error type.
+
+check_error_message(self) -> str:
+    Checks whether the STAC JSON file has an error message.
+
+def check_summaries(self) -> bool:
+    Checks whether the STAC JSON file has summaries.
+
+check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
+    Checks whether the STAC JSON file has bloated links.
+
+check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
+    Checks whether the STAC JSON file has bloated metadata.
+
+check_datetime_null(self) -> bool:
+    Checks whether the STAC JSON file has a null datetime.
+
+check_unlocated(self) -> bool:
+    Checks whether the STAC JSON file has unlocated items.
+
+check_geometry_null(self) -> bool:
+    Checks whether the STAC JSON file has a null geometry.
+
+check_searchable_identifiers(self) -> bool:
+    Checks whether the STAC JSON file has searchable identifiers.
+
+check_percent_encoded(self) -> bool:
+    Checks whether the STAC JSON file has percent-encoded characters.
+
+check_thumbnail(self) -> bool:
+    Checks whether the STAC JSON file has a thumbnail.
+
+check_links_title_field(self) -> bool:
+    Checks whether the STAC JSON file has a title field in its links.
+
+check_links_self(self) -> bool:
+    Checks whether the STAC JSON file has a self link.
+
+check_item_id_file_name(self) -> bool:
+    Checks whether the filename of an Item conforms to the STAC specification.
+
+check_catalog_file_name(self) -> str:
+    Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
+
+create_best_practices_dict(self) -> Dict[str, Any]:
+    Creates a dictionary with best practices recommendations for the STAC JSON file.
+
+create_best_practices_msg(self) -> List[str]:
+    Creates a message with best practices recommendations for the STAC JSON file.
+
+
+ + +
+
- Returns: - bool: A boolean indicating whether the geometry property is null (True) or not (False). - """ - if "geometry" in self.data: - return self.data["geometry"] is None - - def check_searchable_identifiers(self) -> bool: - """Checks if the identifiers of a STAC item are searchable, i.e., - they only contain lowercase letters, numbers, hyphens, and underscores. + Linter( item: Union[str, dict], config_file: Optional[str] = None, assets: bool = False, links: bool = False, recursive: bool = False, max_depth: Optional[int] = None, assets_open_urls: bool = True, headers: dict = <factory>) + - Returns: - bool: True if the identifiers are searchable, False otherwise. - """ - if self.asset_type == "ITEM": - for letter in self.object_id: - if letter.islower() or letter.isnumeric() or letter == '-' or letter == '_': - pass - else: - return False - return True - - def check_percent_encoded(self) -> bool: - """Checks if the identifiers of a STAC item are percent-encoded, i.e., - they only contain lowercase letters, numbers, hyphens, and underscores. - - Returns: - bool: True if the identifiers are percent-encoded, False otherwise. - """ - return self.asset_type == "ITEM" and "/" in self.object_id or ":" in self.object_id - - def check_thumbnail(self) -> bool: - """Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format. +
+ + + + +
+
+
+ item: Union[str, dict] + + +
+ + + + +
+
+
+ config_file: Optional[str] = +None + - Returns: - bool: True if the thumbnail is valid, False otherwise. - """ - if "assets" in self.data: - if "thumbnail" in self.data["assets"]: - if "type" in self.data["assets"]["thumbnail"]: - if "png" in self.data["assets"]["thumbnail"]["type"] or "jpeg" in self.data["assets"]["thumbnail"]["type"] or \ - "jpg" in self.data["assets"]["thumbnail"]["type"] or "webp" in self.data["assets"]["thumbnail"]["type"]: - return True - else: - return False - return True +
+ + - def check_links_title_field(self) -> bool: - """Checks if all links in a STAC collection or catalog have a 'title' field. - The 'title' field is not required for the 'self' link. - - Returns: - bool: True if all links have a 'title' field, False otherwise. - """ - if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG": - for link in self.data["links"]: - if "title" not in link and link["rel"] != "self": - return False - return True - - - def check_links_self(self) -> bool: - """Checks whether the "self" link is present in the STAC collection or catalog or absent in STAC item. + +
+
+
+ assets: bool = +False + - Returns: - bool: True if the "self" link is present in STAC collection or catalog or absent in STAC item, False otherwise. - """ - if self.asset_type == "ITEM": - return True - if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG": - for link in self.data["links"]: - if "self" in link["rel"]: - return True - return False - - def check_item_id_file_name(self) -> bool: - if self.asset_type == "ITEM" and self.object_id != self.file_name: - return False - else: - return True - - def check_catalog_file_name(self) -> bool: - """Checks whether the filename of a Catalog or Collection conforms to the STAC specification. +
+ + + + +
+
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Linter -(item: Union[str, dict], config_file: Optional[str] = None, assets: bool = False, links: bool = False, recursive: bool = False, max_depth: Optional[int] = None) -
-
-

A class for linting STAC JSON files and generating validation messages.

-

Args

-
-
item : Union[str, dict]
-
A URL, file name, or dictionary representing a STAC JSON file.
-
config_file : Optional[str], optional
-
A path to a YAML configuration file. Defaults to None.
-
assets : bool, optional
-
A boolean value indicating whether to validate assets. Defaults to False.
-
links : bool, optional
-
A boolean value indicating whether to validate links. Defaults to False.
-
recursive : bool, optional
-
A boolean value indicating whether to perform recursive validation. Defaults to False.
-
max_depth : Optional[int], optional
-
An optional integer indicating the maximum depth to validate recursively. Defaults to None.
-
-

Attributes

-
-
data : dict
-
A dictionary representing the STAC JSON file.
-
message : dict
-
A dictionary containing the validation message for the STAC JSON file.
-
config : dict
-
A dictionary containing the configuration settings.
-
asset_type : str
-
A string representing the asset type, if one is specified.
-
version : str
-
A string representing the version of the STAC standard used in the STAC JSON file.
-
validator_version : str
-
A string representing the version of the STAC validator used to validate the STAC JSON file.
-
validate_all : dict
-
A dictionary containing the validation message for all STAC JSON files found recursively, if recursive validation was performed.
-
valid_stac : bool
-
A boolean value indicating whether the STAC JSON file is valid.
-
error_type : str
-
A string representing the type of error in the STAC JSON file, if one exists.
-
error_msg : str
-
A string representing the error message in the STAC JSON file, if one exists.
-
invalid_asset_format : List[str]
-
A list of URLs with invalid asset formats, if assets were validated.
-
invalid_asset_request : List[str]
-
A list of URLs with invalid asset requests, if assets were validated.
-
invalid_link_format : List[str]
-
A list of URLs with invalid link formats, if links were validated.
-
invalid_link_request : List[str]
-
A list of URLs with invalid link requests, if links were validated.
-
schema : List[str]
-
A list of the STAC JSON file's JSON schema files.
-
object_id : str
-
A string representing the STAC JSON file's ID.
-
file_name : str
-
A string representing the name of the file containing the STAC JSON data.
-
best_practices_msg : str
-
A string representing best practices messages for the STAC JSON file.
-
-

Methods

-

parse_config(config_file: Optional[str] = None) -> Dict: -Parses a YAML configuration file and returns a dictionary with the configuration settings.

-

def get_asset_name(self, file: Union[str, Dict] = None) -> str: -Returns the name of a file.

-

load_data(self, file: Union[str, Dict]) -> Dict: -Loads a STAC JSON file from a URL or file path and returns a dictionary representation.

-

validate_file(self, file: Union[str, dict]) -> Dict[str, Any]: -Validates a STAC JSON file and returns a dictionary with the validation message.

-

recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str: -Validates a STAC JSON file recursively and returns a dictionary with the validation message.

-

set_update_message(self) -> str: -Sets a message regarding the recommended version of the STAC JSON file standard.

-

check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]: -Checks whether the STAC JSON file has links or assets with invalid formats or requests.

-

check_error_type(self) -> str: -
-Checks whether the STAC JSON file has an error type.

-

check_error_message(self) -> str: -Checks whether the STAC JSON file has an error message.

-

def check_summaries(self) -> bool: -Checks whether the STAC JSON file has summaries.

-

check_bloated_links(self, max_links: Optional[int] = 20) -> bool: -Checks whether the STAC JSON file has bloated links.

-

check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool: -Checks whether the STAC JSON file has bloated metadata.

-

check_datetime_null(self) -> bool: -Checks whether the STAC JSON file has a null datetime.

-

check_unlocated(self) -> bool: -Checks whether the STAC JSON file has unlocated items.

-

check_geometry_null(self) -> bool: -Checks whether the STAC JSON file has a null geometry. -

-

check_searchable_identifiers(self) -> bool: -Checks whether the STAC JSON file has searchable identifiers.

-

check_percent_encoded(self) -> bool: -Checks whether the STAC JSON file has percent-encoded characters.

-

check_thumbnail(self) -> bool: -Checks whether the STAC JSON file has a thumbnail.

-

check_links_title_field(self) -> bool: -Checks whether the STAC JSON file has a title field in its links.

-

check_links_self(self) -> bool: -Checks whether the STAC JSON file has a self link.

-

check_item_id_file_name(self) -> bool: -Checks whether the filename of an Item conforms to the STAC specification.

-

check_catalog_file_name(self) -> str: -Checks whether the filename of a Catalog or Collection conforms to the STAC specification.

-

create_best_practices_dict(self) -> Dict[str, Any]: -Creates a dictionary with best practices recommendations for the STAC JSON file.

-

create_best_practices_msg(self) -> List[str]: -Creates a message with best practices recommendations for the STAC JSON file.

-
- -Expand source code - -
@dataclass
-class Linter:
-    """A class for linting STAC JSON files and generating validation messages.
-
-    Args:
-        item (Union[str, dict]): A URL, file name, or dictionary representing a STAC JSON file.
-        config_file (Optional[str], optional): A path to a YAML configuration file. Defaults to None.
-        assets (bool, optional): A boolean value indicating whether to validate assets. Defaults to False.
-        links (bool, optional): A boolean value indicating whether to validate links. Defaults to False.
-        recursive (bool, optional): A boolean value indicating whether to perform recursive validation. Defaults to False.
-        max_depth (Optional[int], optional): An optional integer indicating the maximum depth to validate recursively. Defaults to None.
-
-    Attributes:
-        data (dict): A dictionary representing the STAC JSON file.
-        message (dict): A dictionary containing the validation message for the STAC JSON file.
-        config (dict): A dictionary containing the configuration settings.
-        asset_type (str): A string representing the asset type, if one is specified.
-        version (str): A string representing the version of the STAC standard used in the STAC JSON file.
-        validator_version (str): A string representing the version of the STAC validator used to validate the STAC JSON file.
-        validate_all (dict): A dictionary containing the validation message for all STAC JSON files found recursively, if recursive validation was performed.
-        valid_stac (bool): A boolean value indicating whether the STAC JSON file is valid.
-        error_type (str): A string representing the type of error in the STAC JSON file, if one exists.
-        error_msg (str): A string representing the error message in the STAC JSON file, if one exists.
-        invalid_asset_format (List[str]): A list of URLs with invalid asset formats, if assets were validated.
-        invalid_asset_request (List[str]): A list of URLs with invalid asset requests, if assets were validated.
-        invalid_link_format (List[str]): A list of URLs with invalid link formats, if links were validated.
-        invalid_link_request (List[str]): A list of URLs with invalid link requests, if links were validated.
-        schema (List[str]): A list of the STAC JSON file's JSON schema files.
-        object_id (str): A string representing the STAC JSON file's ID.
-        file_name (str): A string representing the name of the file containing the STAC JSON data.
-        best_practices_msg (str): A string representing best practices messages for the STAC JSON file.
-
-    Methods:
-        parse_config(config_file: Optional[str] = None) -> Dict:
-            Parses a YAML configuration file and returns a dictionary with the configuration settings.
-
-        def get_asset_name(self, file: Union[str, Dict] = None) -> str:
-            Returns the name of a file.
-
-        load_data(self, file: Union[str, Dict]) -> Dict:
-            Loads a STAC JSON file from a URL or file path and returns a dictionary representation.
-
-        validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
-            Validates a STAC JSON file and returns a dictionary with the validation message.
-
-        recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
-            Validates a STAC JSON file recursively and returns a dictionary with the validation message.
-
-        set_update_message(self) -> str:
-            Sets a message regarding the recommended version of the STAC JSON file standard.
-
-        check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
-            Checks whether the STAC JSON file has links or assets with invalid formats or requests.
-
-        check_error_type(self) -> str:                  
-            Checks whether the STAC JSON file has an error type.
-
-        check_error_message(self) -> str:
-            Checks whether the STAC JSON file has an error message. 
-
-        def check_summaries(self) -> bool:
-            Checks whether the STAC JSON file has summaries.
-
-        check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
-            Checks whether the STAC JSON file has bloated links.
-
-        check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
-            Checks whether the STAC JSON file has bloated metadata.
-
-        check_datetime_null(self) -> bool:
-            Checks whether the STAC JSON file has a null datetime.
-
-        check_unlocated(self) -> bool:
-            Checks whether the STAC JSON file has unlocated items.
-
-        check_geometry_null(self) -> bool:
-            Checks whether the STAC JSON file has a null geometry.  
-
-        check_searchable_identifiers(self) -> bool: 
-            Checks whether the STAC JSON file has searchable identifiers.
-
-        check_percent_encoded(self) -> bool:
-            Checks whether the STAC JSON file has percent-encoded characters.
-
-        check_thumbnail(self) -> bool:
-            Checks whether the STAC JSON file has a thumbnail.
-
-        check_links_title_field(self) -> bool:
-            Checks whether the STAC JSON file has a title field in its links.
-
-        check_links_self(self) -> bool:
-            Checks whether the STAC JSON file has a self link.
-
-        check_item_id_file_name(self) -> bool:
-            Checks whether the filename of an Item conforms to the STAC specification.
-
-        check_catalog_file_name(self) -> str:
-            Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
-
-        create_best_practices_dict(self) -> Dict[str, Any]:
-            Creates a dictionary with best practices recommendations for the STAC JSON file.
-
-        create_best_practices_msg(self) -> List[str]:
-            Creates a message with best practices recommendations for the STAC JSON file.
-    """
-    item: Union[str, dict] # url, file name, or dictionary
-    config_file: Optional[str] = None
-    assets: bool = False
-    links: bool = False
-    recursive: bool = False
-    max_depth: Optional[int] = None
-
-    def __post_init__(self):
-        self.data = self.load_data(self.item)
-        self.message = self.validate_file(self.item)
-        self.config = self.parse_config(self.config_file)
-        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 = pkg_resources.require("stac-validator")[0].version
-        self.validate_all = self.recursive_validation(self.item)
-        self.valid_stac = self.message["valid_stac"]
-        self.error_type = self.check_error_type()
-        self.error_msg = self.check_error_message()
-        self.invalid_asset_format = self.check_links_assets(10, "assets", "format") if self.assets else None
-        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.message["schema"] if "schema" in self.message else []
-        self.object_id = self.data["id"] if "id" in self.data else ""
-        self.file_name = self.get_asset_name(self.item)
-        self.best_practices_msg = self.create_best_practices_msg()
-
-    @staticmethod
-    def parse_config(config_file: Optional[str] = None) -> Dict:
-        """Parse the configuration file for STAC checks.
-
-        The method first looks for a file path specified in the `STAC_CHECK_CONFIG`
-        environment variable. If the variable is defined, the method loads the
-        YAML configuration file located at that path. Otherwise, it loads the default
-        configuration file packaged with the `stac-check` module.
-
-        If `config_file` is specified, the method also loads the YAML configuration
-        file located at that path and merges its contents with the default or
-        environment-based configuration.
-
-        Args:
-            config_file (str): The path to the YAML configuration file.
-
-        Returns:
-            A dictionary containing the parsed configuration values.
-
-        Raises:
-            IOError: If `config_file` is specified but cannot be read.
-            yaml.YAMLError: If any YAML syntax errors occur while parsing the
-                configuration file(s).
-        """
-        default_config_file = os.getenv("STAC_CHECK_CONFIG")
-        if default_config_file:
-            with open(default_config_file) as f:
-                default_config = yaml.load(f, Loader=yaml.FullLoader)
-        else:
-            with pkg_resources.resource_stream(__name__, "stac-check.config.yml") as f:
-                default_config = yaml.load(f, Loader=yaml.FullLoader)
-        if config_file:
-            with open(config_file) as f:
-                config = yaml.load(f, Loader=yaml.FullLoader)
-            default_config.update(config)
-            
-        return default_config
-
-    def get_asset_name(self, file: Union[str, Dict] = None) -> str:
-        """Extracts the name of an asset from its file path or from a STAC item asset dictionary.
-
-        Args:
-            file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the
-                asset as specified in a STAC item's `assets` property.
-
-        Returns:
-            A string containing the name of the asset.
-
-        Raises:
-            TypeError: If the input `file` is not a string or a dictionary.
-        """
-        if isinstance(file, str):
-            return os.path.basename(file).split('.')[0]
-        else:
-            return file["id"]
-
-    def load_data(self, file: Union[str, Dict]) -> Dict:
-        """Loads JSON data from a file or URL.
-
-        Args:
-            file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.
-
-        Returns:
-            A dictionary containing the loaded JSON data.
-
-        Raises:
-            TypeError: If the input `file` is not a string or dictionary.
-            ValueError: If `file` is a string that doesn't represent a valid URL or file path.
-            requests.exceptions.RequestException: If there is an error making a request to a URL.
-            JSONDecodeError: If the JSON data cannot be decoded.
-            FileNotFoundError: If the specified file cannot be found.
-        """
-
-        if isinstance(file, str):
-            if is_valid_url(file):
-                resp = requests.get(file)
-                data = resp.json()
-            else:
-                with open(file) as json_file:
-                    data = json.load(json_file)
-            return data
-        else:
-            return file
-
-    def validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
-        """Validates the given file path or STAC dictionary against the validation schema.
-
-        Args:
-            file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC
-                item.
-
-        Returns:
-            A dictionary containing the results of the validation, including the status of the validation and any errors
-            encountered.
-
-        Raises:
-            ValueError: If `file` is not a valid file path or STAC dictionary.
-        """
-        if isinstance(file, str):
-            stac = StacValidate(file, links=self.links, assets=self.assets)
-            stac.run()
-        elif isinstance(file, dict):
-            stac = StacValidate()
-            stac.validate_dict(file)
-        else:
-            raise ValueError("Input must be a file path or STAC dictionary.")
-        return stac.message[0]
-
-    def recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
-        """Recursively validate a STAC item or catalog file and its child items.
-
-        Args:
-            file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a
-                dictionary representing the STAC item or catalog.
-
-        Returns:
-            A string containing the validation message.
-
-        Raises:
-            TypeError: If the input `file` is not a string or a dictionary.
-        """
-        if self.recursive:
-            if isinstance(file, str):
-                stac = StacValidate(file, recursive=True, max_depth=self.max_depth)
-                stac.run()
-            else:
-                stac = StacValidate(recursive=True, max_depth=self.max_depth)
-                stac.validate_dict(file)
-            return stac.message
-
-    def set_update_message(self) -> str:
-        """Returns a message for users to update their STAC version.
-
-        Returns:
-            A string containing a message for users to update their STAC version.
-        """
-        if self.version != "1.0.0":
-            return f"Please upgrade from version {self.version} to version 1.0.0!"
-        else:
-            return "Thanks for using STAC version 1.0.0!"
-
-    def check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
-        """Checks the links and assets in the STAC catalog and returns a list of invalid links of a specified type and format.
-
-        Args:
-            num_links (int): The maximum number of invalid links to return.
-            url_type (str): The type of URL to check, which can be either 'self' or 'external'.
-            format_type (str): The format of the URL to check, which can be either 'html' or 'json'.
-
-        Returns:
-            A list of invalid links of the specified type and format. If there are no invalid links, an empty list is returned.
-        """
-        links = []
-        if f"{url_type}_validated" in self.message:
-            for invalid_request_url in self.message[f"{url_type}_validated"][f"{format_type}_invalid"]:
-                if invalid_request_url not in links and 'http' in invalid_request_url:
-                    links.append(invalid_request_url)
-                num_links = num_links - 1
-                if num_links == 0:
-                    return links
-        return links
-
-    def check_error_type(self) -> str:
-        """Returns the error type of a STAC validation if it exists in the validation message, 
-        and an empty string otherwise.
-
-        Returns:
-            str: A string containing the error type of a STAC validation if it exists in the validation message, and an
-            empty string otherwise.
-        """
-        if "error_type" in self.message:
-            return self.message["error_type"]
-        else:
-            return ""
-
-    def check_error_message(self) -> str:
-        """Checks whether the `message` attribute contains an `error_message` field.
-
-        Returns:
-            A string containing the value of the `error_message` field, or an empty string if the field is not present.
-        """
-        if "error_message" in self.message:
-            return self.message["error_message"]
-        else:
-            return ""
-
-    def check_summaries(self) -> bool:
-        """Check if a Collection asset has a "summaries" property.
-
-        Returns:
-            A boolean indicating whether the Collection asset has a "summaries" property.
-        """
-        if self.asset_type == "COLLECTION":
-            return "summaries" in self.data
-
-    def check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
-        """Checks if the number of links in the STAC data exceeds a certain maximum.
-
-        Args:
-            max_links (Optional[int]): The maximum number of links that the STAC data is allowed to have. Default is 20.
-
-        Returns:
-            bool: A boolean indicating if the number of links in the STAC data exceeds the specified maximum.
-        """
-        if "links" in self.data:
-            return len(self.data["links"]) > max_links
-
-    def check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
-        """Checks whether a STAC item's metadata contains too many properties.
-
-        Args:
-            max_properties (int, optional): The maximum number of properties that the metadata can contain before it is
-                considered too bloated. Defaults to 20.
-
-        Returns:
-            bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by
-                `max_properties`, False otherwise.
-        """
-        if "properties" in self.data:
-            return len(self.data["properties"].keys()) > max_properties
-        return False
-
-    def check_datetime_null(self) -> bool:
-        """Checks if the STAC item has a null datetime property.
-
-        Returns:
-            bool: A boolean indicating whether the datetime property is null (True) or not (False).
-        """
-        if "properties" in self.data:
-            if "datetime" in self.data["properties"]:
-                if self.data["properties"]["datetime"] == None:
-                    return True
-        else:
-            return False
-        return False
-
-    def check_unlocated(self) -> bool:
-        """Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.
-
-        Returns:
-            bool: True if the STAC item is unlocated, False otherwise.
-        """
-        if "geometry" in self.data:
-            return self.data["geometry"] is None and self.data["bbox"] is not None
-
-    def check_geometry_null(self) -> bool:
-        """Checks if a STAC item has a null geometry property.
-            
-        Returns:
-            bool: A boolean indicating whether the geometry property is null (True) or not (False).          
-        """
-        if "geometry" in self.data:
-            return self.data["geometry"] is None
-
-    def check_searchable_identifiers(self) -> bool:
-        """Checks if the identifiers of a STAC item are searchable, i.e., 
-        they only contain lowercase letters, numbers, hyphens, and underscores.
+    
+    
+    
+    
+
+                            
+                            
+
+ recursive: bool = +False + - Returns: - bool: True if the identifiers are searchable, False otherwise. - """ - if self.asset_type == "ITEM": - for letter in self.object_id: - if letter.islower() or letter.isnumeric() or letter == '-' or letter == '_': - pass - else: - return False - return True - - def check_percent_encoded(self) -> bool: - """Checks if the identifiers of a STAC item are percent-encoded, i.e., - they only contain lowercase letters, numbers, hyphens, and underscores. - - Returns: - bool: True if the identifiers are percent-encoded, False otherwise. - """ - return self.asset_type == "ITEM" and "/" in self.object_id or ":" in self.object_id - - def check_thumbnail(self) -> bool: - """Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format. +
+ + + + +
+
+
+ max_depth: Optional[int] = +None + - Returns: - bool: True if the thumbnail is valid, False otherwise. - """ - if "assets" in self.data: - if "thumbnail" in self.data["assets"]: - if "type" in self.data["assets"]["thumbnail"]: - if "png" in self.data["assets"]["thumbnail"]["type"] or "jpeg" in self.data["assets"]["thumbnail"]["type"] or \ - "jpg" in self.data["assets"]["thumbnail"]["type"] or "webp" in self.data["assets"]["thumbnail"]["type"]: - return True - else: - return False - return True +
+ + - def check_links_title_field(self) -> bool: - """Checks if all links in a STAC collection or catalog have a 'title' field. - The 'title' field is not required for the 'self' link. - - Returns: - bool: True if all links have a 'title' field, False otherwise. - """ - if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG": - for link in self.data["links"]: - if "title" not in link and link["rel"] != "self": - return False - return True - - - def check_links_self(self) -> bool: - """Checks whether the "self" link is present in the STAC collection or catalog or absent in STAC item. + +
+
+
+ assets_open_urls: bool = +True + - Returns: - bool: True if the "self" link is present in STAC collection or catalog or absent in STAC item, False otherwise. - """ - if self.asset_type == "ITEM": - return True - if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG": - for link in self.data["links"]: - if "self" in link["rel"]: - return True - return False - - def check_item_id_file_name(self) -> bool: - if self.asset_type == "ITEM" and self.object_id != self.file_name: - return False - else: - return True - - def check_catalog_file_name(self) -> bool: - """Checks whether the filename of a Catalog or Collection conforms to the STAC specification. +
+ + + + +
+
+
+ headers: dict + - Returns: - bool: True if the filename is valid, False otherwise. - """ - if isinstance(self.item, str) and ".json" in self.item: - if self.asset_type == "CATALOG" and 'catalog.json' not in self.item: - return False - elif self.asset_type == "COLLECTION" and 'collection.json' not in self.item: - return False - return True - else: - return True - - def create_best_practices_dict(self) -> Dict: - """Creates a dictionary of best practices violations for the current STAC object. The violations are determined - by a set of configurable linting rules specified in the config file. - - Returns: - A dictionary of best practices violations for the current STAC object. The keys in the dictionary correspond - to the linting rules that were violated, and the values are lists of strings containing error messages and - recommendations for how to fix the violations. - """ - best_practices_dict = {} - config = self.config["linting"] - max_links = self.config["settings"]["max_links"] - max_properties = self.config["settings"]["max_properties"] - - # best practices - item ids should only contain searchable identifiers - if self.check_searchable_identifiers() == False and config["searchable_identifiers"] == True: - msg_1 = f"Item name '{self.object_id}' should only contain Searchable identifiers" - msg_2 = f"Identifiers should consist of only lowercase characters, numbers, '_', and '-'" - best_practices_dict["searchable_identifiers"] = [msg_1, msg_2] - - # best practices - item ids should not contain ':' or '/' characters - if self.check_percent_encoded() and config["percent_encoded"] == True: - msg_1 = f"Item name '{self.object_id}' should not contain ':' or '/'" - msg_2 = f"https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#item-ids" - best_practices_dict["percent_encoded"] = [msg_1, msg_2] - - # best practices - item ids should match file names - if not self.check_item_id_file_name() and config["item_id_file_name"] == True: - msg_1 = f"Item file names should match their ids: '{self.file_name}' not equal to '{self.object_id}" - best_practices_dict["check_item_id"] = [msg_1] - - # best practices - collection and catalog file names should be collection.json and catalog.json - if self.check_catalog_file_name() == False and config["catalog_id_file_name"] == True: - msg_1 = f"Object should be called '{self.asset_type.lower()}.json' not '{self.file_name}.json'" - best_practices_dict["check_catalog_id"] = [msg_1] - - # best practices - collections should contain summaries - if self.check_summaries() == False and config["check_summaries"] == True: - msg_1 = f"A STAC collection should contain a summaries field" - msg_2 = f"It is recommended to store information like eo:bands in summaries" - best_practices_dict["check_summaries"] = [msg_1, msg_2] - - # best practices - datetime fields should not be set to null - if self.check_datetime_null() and config["null_datetime"] == True: - msg_1 = f"Please avoid setting the datetime field to null, many clients search on this field" - best_practices_dict["datetime_null"] = [msg_1] - - # best practices - check unlocated items to make sure bbox field is not set - if self.check_unlocated() and config["check_unlocated"] == True: - msg_1 = f"Unlocated item. Please avoid setting the bbox field when geometry is set to null" - best_practices_dict["check_unlocated"] = [msg_1] - - # best practices - recommend items have a geometry - if self.check_geometry_null() and config["check_geometry"] == True: - msg_1 = f"All items should have a geometry field. STAC is not meant for non-spatial data" - best_practices_dict["null_geometry"] = [msg_1] - - # check to see if there are too many links - if self.check_bloated_links(max_links=max_links) and config["bloated_links"] == True: - msg_1 = f"You have {len(self.data['links'])} links. Please consider using sub-collections or sub-catalogs" - best_practices_dict["bloated_links"] = [msg_1] - - # best practices - check for bloated metadata in properties - if self.check_bloated_metadata(max_properties=max_properties) and config["bloated_metadata"] == True: - msg_1 = f"You have {len(self.data['properties'])} properties. Please consider using links to avoid bloated metadata" - best_practices_dict["bloated_metadata"] = [msg_1] - - # best practices - ensure thumbnail is a small file size ["png", "jpeg", "jpg", "webp"] - if not self.check_thumbnail() and self.asset_type == "ITEM" and config["check_thumbnail"] == True: - msg_1 = f"A thumbnail should have a small file size ie. png, jpeg, jpg, webp" - best_practices_dict["check_thumbnail"] = [msg_1] - - # best practices - ensure that links in catalogs and collections include a title field - if not self.check_links_title_field() and config["links_title"] == True: - msg_1 = f"Links in catalogs and collections should always have a 'title' field" - best_practices_dict["check_links_title"] = [msg_1] - - # best practices - ensure that links in catalogs and collections include self link - if not self.check_links_self() and config["links_self"] == True: - msg_1 = f"A link to 'self' in links is strongly recommended" - best_practices_dict["check_links_self"] = [msg_1] - - return best_practices_dict - - def create_best_practices_msg(self) -> List[str]: - """ - Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method. - - Returns: - A list of strings, where each string contains a best practice message. Each message starts with the - 'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented - with four spaces, and there is an empty string between each message for readability. - """ - best_practices = list() - base_string = "STAC Best Practices: " - best_practices.append(base_string) - - for _,v in self.create_best_practices_dict().items(): - for value in v: - best_practices.extend([" " +value]) - best_practices.extend([""]) - - return best_practices
-
-

Class variables

-
-
var assets : bool
-
-
-
-
var config_file : Optional[str]
-
-
-
-
var item : Union[str, dict]
-
-
-
- -
-
-
-
var max_depth : Optional[int]
-
-
-
-
var recursive : bool
-
-
-
-
-

Static methods

-
-
-def parse_config(config_file: Optional[str] = None) ‑> Dict -
-
-

Parse the configuration file for STAC checks.

+
+ + + + + +
+ +
+
@staticmethod
+ + def + parse_config(config_file: Optional[str] = None) -> Dict: + + + +
+ +
167    @staticmethod
+168    def parse_config(config_file: Optional[str] = None) -> Dict:
+169        """Parse the configuration file for STAC checks.
+170
+171        The method first looks for a file path specified in the `STAC_CHECK_CONFIG`
+172        environment variable. If the variable is defined, the method loads the
+173        YAML configuration file located at that path. Otherwise, it loads the default
+174        configuration file packaged with the `stac-check` module.
+175
+176        If `config_file` is specified, the method also loads the YAML configuration
+177        file located at that path and merges its contents with the default or
+178        environment-based configuration.
+179
+180        Args:
+181            config_file (str): The path to the YAML configuration file.
+182
+183        Returns:
+184            A dictionary containing the parsed configuration values.
+185
+186        Raises:
+187            IOError: If `config_file` is specified but cannot be read.
+188            yaml.YAMLError: If any YAML syntax errors occur while parsing the
+189                configuration file(s).
+190        """
+191        default_config_file = os.getenv("STAC_CHECK_CONFIG")
+192        if default_config_file:
+193            with open(default_config_file) as f:
+194                default_config = yaml.load(f, Loader=yaml.FullLoader)
+195        else:
+196            with importlib.resources.open_text(
+197                "stac_check", "stac-check.config.yml"
+198            ) as f:
+199                default_config = yaml.load(f, Loader=yaml.FullLoader)
+200        if config_file:
+201            with open(config_file) as f:
+202                config = yaml.load(f, Loader=yaml.FullLoader)
+203            default_config.update(config)
+204
+205        return default_config
+
+ + +

Parse the configuration file for STAC checks.

+

The method first looks for a file path specified in the STAC_CHECK_CONFIG environment variable. If the variable is defined, the method loads the YAML configuration file located at that path. Otherwise, it loads the default configuration file packaged with the stac-check module.

-

If config_file is specified, the method also loads the YAML configuration + +

If config_file is specified, the method also loads the YAML configuration file located at that path and merges its contents with the default or environment-based configuration.

-

Args

-
-
config_file : str
-
The path to the YAML configuration file.
-
-

Returns

-

A dictionary containing the parsed configuration values.

-

Raises

-
-
IOError
-
If config_file is specified but cannot be read.
-
yaml.YAMLError
-
If any YAML syntax errors occur while parsing the -configuration file(s).
-
-
- -Expand source code - -
@staticmethod
-def parse_config(config_file: Optional[str] = None) -> Dict:
-    """Parse the configuration file for STAC checks.
-
-    The method first looks for a file path specified in the `STAC_CHECK_CONFIG`
-    environment variable. If the variable is defined, the method loads the
-    YAML configuration file located at that path. Otherwise, it loads the default
-    configuration file packaged with the `stac-check` module.
-
-    If `config_file` is specified, the method also loads the YAML configuration
-    file located at that path and merges its contents with the default or
-    environment-based configuration.
-
-    Args:
-        config_file (str): The path to the YAML configuration file.
-
-    Returns:
-        A dictionary containing the parsed configuration values.
-
-    Raises:
-        IOError: If `config_file` is specified but cannot be read.
-        yaml.YAMLError: If any YAML syntax errors occur while parsing the
-            configuration file(s).
-    """
-    default_config_file = os.getenv("STAC_CHECK_CONFIG")
-    if default_config_file:
-        with open(default_config_file) as f:
-            default_config = yaml.load(f, Loader=yaml.FullLoader)
-    else:
-        with pkg_resources.resource_stream(__name__, "stac-check.config.yml") as f:
-            default_config = yaml.load(f, Loader=yaml.FullLoader)
-    if config_file:
-        with open(config_file) as f:
-            config = yaml.load(f, Loader=yaml.FullLoader)
-        default_config.update(config)
-        
-    return default_config
-
-
-
-

Methods

-
- -
-

Checks if the number of links in the STAC data exceeds a certain maximum.

-

Args

-
-
max_links : Optional[int]
-
The maximum number of links that the STAC data is allowed to have. Default is 20.
-
-

Returns

-
-
bool
-
A boolean indicating if the number of links in the STAC data exceeds the specified maximum.
-
-
- -Expand source code - -
def check_bloated_links(self, max_links: Optional[int] = 20) -> bool:
-    """Checks if the number of links in the STAC data exceeds a certain maximum.
-
-    Args:
-        max_links (Optional[int]): The maximum number of links that the STAC data is allowed to have. Default is 20.
-
-    Returns:
-        bool: A boolean indicating if the number of links in the STAC data exceeds the specified maximum.
-    """
-    if "links" in self.data:
-        return len(self.data["links"]) > max_links
-
-
-
-def check_bloated_metadata(self, max_properties: Optional[int] = 20) ‑> bool -
-
-

Checks whether a STAC item's metadata contains too many properties.

-

Args

-
-
max_properties : int, optional
-
The maximum number of properties that the metadata can contain before it is -considered too bloated. Defaults to 20.
-
-

Returns

-
-
bool
-
True if the number of properties in the metadata exceeds the maximum number of properties specified by -max_properties, False otherwise.
-
-
- -Expand source code - -
def check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
-    """Checks whether a STAC item's metadata contains too many properties.
-
-    Args:
-        max_properties (int, optional): The maximum number of properties that the metadata can contain before it is
-            considered too bloated. Defaults to 20.
-
-    Returns:
-        bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by
-            `max_properties`, False otherwise.
-    """
-    if "properties" in self.data:
-        return len(self.data["properties"].keys()) > max_properties
-    return False
-
-
-
-def check_catalog_file_name(self) ‑> bool -
-
-

Checks whether the filename of a Catalog or Collection conforms to the STAC specification.

-

Returns

-
-
bool
-
True if the filename is valid, False otherwise.
-
-
- -Expand source code - -
def check_catalog_file_name(self) -> bool:
-    """Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
-    
-    Returns:
-        bool: True if the filename is valid, False otherwise.
-    """
-    if isinstance(self.item, str) and ".json" in self.item:
-        if self.asset_type == "CATALOG" and 'catalog.json' not in self.item:
-            return False 
-        elif self.asset_type == "COLLECTION" and 'collection.json' not in self.item:
-            return False
-        return True
-    else:
-        return True
-
-
-
-def check_datetime_null(self) ‑> bool -
-
-

Checks if the STAC item has a null datetime property.

-

Returns

-
-
bool
-
A boolean indicating whether the datetime property is null (True) or not (False).
-
-
- -Expand source code - -
def check_datetime_null(self) -> bool:
-    """Checks if the STAC item has a null datetime property.
-
-    Returns:
-        bool: A boolean indicating whether the datetime property is null (True) or not (False).
-    """
-    if "properties" in self.data:
-        if "datetime" in self.data["properties"]:
-            if self.data["properties"]["datetime"] == None:
-                return True
-    else:
-        return False
-    return False
-
-
-
-def check_error_message(self) ‑> str -
-
-

Checks whether the message attribute contains an error_message field.

-

Returns

-

A string containing the value of the error_message field, or an empty string if the field is not present.

-
- -Expand source code - -
def check_error_message(self) -> str:
-    """Checks whether the `message` attribute contains an `error_message` field.
-
-    Returns:
-        A string containing the value of the `error_message` field, or an empty string if the field is not present.
-    """
-    if "error_message" in self.message:
-        return self.message["error_message"]
-    else:
-        return ""
-
-
-
-def check_error_type(self) ‑> str -
-
-

Returns the error type of a STAC validation if it exists in the validation message, + +

Args: + config_file (str): The path to the YAML configuration file.

+ +

Returns: + A dictionary containing the parsed configuration values.

+ +

Raises: + IOError: If config_file is specified but cannot be read. + yaml.YAMLError: If any YAML syntax errors occur while parsing the + configuration file(s).

+
+ + + +
+ +
+ + def + get_asset_name(self, file: Union[str, Dict] = None) -> str: + + + +
+ +
207    def get_asset_name(self, file: Union[str, Dict] = None) -> str:
+208        """Extracts the name of an asset from its file path or from a STAC item asset dictionary.
+209
+210        Args:
+211            file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the
+212                asset as specified in a STAC item's `assets` property.
+213
+214        Returns:
+215            A string containing the name of the asset.
+216
+217        Raises:
+218            TypeError: If the input `file` is not a string or a dictionary.
+219        """
+220        if isinstance(file, str):
+221            return os.path.basename(file).split(".")[0]
+222        else:
+223            return file["id"]
+
+ + +

Extracts the name of an asset from its file path or from a STAC item asset dictionary.

+ +

Args: + file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the + asset as specified in a STAC item's assets property.

+ +

Returns: + A string containing the name of the asset.

+ +

Raises: + TypeError: If the input file is not a string or a dictionary.

+
+ + +
+
+ +
+ + def + load_data(self, file: Union[str, Dict]) -> Dict: + + + +
+ +
225    def load_data(self, file: Union[str, Dict]) -> Dict:
+226        """Loads JSON data from a file or URL.
+227
+228        Args:
+229            file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.
+230
+231        Returns:
+232            A dictionary containing the loaded JSON data.
+233
+234        Raises:
+235            TypeError: If the input `file` is not a string or dictionary.
+236            ValueError: If `file` is a string that doesn't represent a valid URL or file path.
+237            requests.exceptions.RequestException: If there is an error making a request to a URL.
+238            JSONDecodeError: If the JSON data cannot be decoded.
+239            FileNotFoundError: If the specified file cannot be found.
+240        """
+241
+242        if isinstance(file, str):
+243            if is_valid_url(file):
+244                resp = requests.get(file, headers=self.headers)
+245                data = resp.json()
+246            else:
+247                with open(file) as json_file:
+248                    data = json.load(json_file)
+249            return data
+250        else:
+251            return file
+
+ + +

Loads JSON data from a file or URL.

+ +

Args: + file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.

+ +

Returns: + A dictionary containing the loaded JSON data.

+ +

Raises: + TypeError: If the input file is not a string or dictionary. + ValueError: If file is a string that doesn't represent a valid URL or file path. + requests.exceptions.RequestException: If there is an error making a request to a URL. + JSONDecodeError: If the JSON data cannot be decoded. + FileNotFoundError: If the specified file cannot be found.

+
+ + +
+
+ +
+ + def + validate_file(self, file: Union[str, dict]) -> Dict[str, Any]: + + + +
+ +
253    def validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
+254        """Validates the given file path or STAC dictionary against the validation schema.
+255
+256        Args:
+257            file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC
+258                item.
+259
+260        Returns:
+261            A dictionary containing the results of the validation, including the status of the validation and any errors
+262            encountered.
+263
+264        Raises:
+265            ValueError: If `file` is not a valid file path or STAC dictionary.
+266        """
+267        if isinstance(file, str):
+268            stac = StacValidate(
+269                file,
+270                links=self.links,
+271                assets=self.assets,
+272                assets_open_urls=self.assets_open_urls,
+273                headers=self.headers,
+274            )
+275            stac.run()
+276        elif isinstance(file, dict):
+277            stac = StacValidate(
+278                assets_open_urls=self.assets_open_urls, headers=self.headers
+279            )
+280            stac.validate_dict(file)
+281        else:
+282            raise ValueError("Input must be a file path or STAC dictionary.")
+283        return stac.message[0]
+
+ + +

Validates the given file path or STAC dictionary against the validation schema.

+ +

Args: + file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC + item.

+ +

Returns: + A dictionary containing the results of the validation, including the status of the validation and any errors + encountered.

+ +

Raises: + ValueError: If file is not a valid file path or STAC dictionary.

+
+ + +
+
+ +
+ + def + recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str: + + + +
+ +
285    def recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
+286        """Recursively validate a STAC item or catalog file and its child items.
+287
+288        Args:
+289            file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a
+290                dictionary representing the STAC item or catalog.
+291
+292        Returns:
+293            A string containing the validation message.
+294
+295        Raises:
+296            TypeError: If the input `file` is not a string or a dictionary.
+297        """
+298        if self.recursive:
+299            if isinstance(file, str):
+300                stac = StacValidate(
+301                    file,
+302                    recursive=True,
+303                    max_depth=self.max_depth,
+304                    assets_open_urls=self.assets_open_urls,
+305                    headers=self.headers,
+306                )
+307                stac.run()
+308            else:
+309                stac = StacValidate(
+310                    recursive=True,
+311                    max_depth=self.max_depth,
+312                    assets_open_urls=self.assets_open_urls,
+313                    headers=self.headers,
+314                )
+315                stac.validate_dict(file)
+316            return stac.message
+317        else:
+318            return "Recursive validation is disabled."
+
+ + +

Recursively validate a STAC item or catalog file and its child items.

+ +

Args: + file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a + dictionary representing the STAC item or catalog.

+ +

Returns: + A string containing the validation message.

+ +

Raises: + TypeError: If the input file is not a string or a dictionary.

+
+ + +
+
+ +
+ + def + set_update_message(self) -> str: + + + +
+ +
320    def set_update_message(self) -> str:
+321        """Returns a message for users to update their STAC version.
+322
+323        Returns:
+324            A string containing a message for users to update their STAC version.
+325        """
+326        if self.version != "1.0.0":
+327            return f"Please upgrade from version {self.version} to version 1.0.0!"
+328        else:
+329            return "Thanks for using STAC version 1.0.0!"
+
+ + +

Returns a message for users to update their STAC version.

+ +

Returns: + A string containing a message for users to update their STAC version.

+
+ + +
+ +
+ +
+ + def + check_error_type(self) -> str: + + + +
+ +
356    def check_error_type(self) -> str:
+357        """Returns the error type of a STAC validation if it exists in the validation message,
+358        and an empty string otherwise.
+359
+360        Returns:
+361            str: A string containing the error type of a STAC validation if it exists in the validation message, and an
+362            empty string otherwise.
+363        """
+364        if "error_type" in self.message:
+365            return self.message["error_type"]
+366        else:
+367            return ""
+
+ + +

Returns the error type of a STAC validation if it exists in the validation message, and an empty string otherwise.

-

Returns

-
-
str
-
A string containing the error type of a STAC validation if it exists in the validation message, and an
-
-

empty string otherwise.

-
- -Expand source code - -
def check_error_type(self) -> str:
-    """Returns the error type of a STAC validation if it exists in the validation message, 
-    and an empty string otherwise.
-
-    Returns:
-        str: A string containing the error type of a STAC validation if it exists in the validation message, and an
-        empty string otherwise.
-    """
-    if "error_type" in self.message:
-        return self.message["error_type"]
-    else:
-        return ""
-
-
-
-def check_geometry_null(self) ‑> bool -
-
-

Checks if a STAC item has a null geometry property.

-

Returns

-
-
bool
-
A boolean indicating whether the geometry property is null (True) or not (False).
-
-
- -Expand source code - -
def check_geometry_null(self) -> bool:
-    """Checks if a STAC item has a null geometry property.
-        
-    Returns:
-        bool: A boolean indicating whether the geometry property is null (True) or not (False).          
-    """
-    if "geometry" in self.data:
-        return self.data["geometry"] is None
-
-
-
-def check_item_id_file_name(self) ‑> bool -
-
-
-
- -Expand source code - -
def check_item_id_file_name(self) -> bool:
-    if self.asset_type == "ITEM" and self.object_id != self.file_name:
-        return False
-    else:
-        return True
-
-
- -
-

Checks the links and assets in the STAC catalog and returns a list of invalid links of a specified type and format.

-

Args

-
-
num_links : int
-
The maximum number of invalid links to return.
-
url_type : str
-
The type of URL to check, which can be either 'self' or 'external'.
-
format_type : str
-
The format of the URL to check, which can be either 'html' or 'json'.
-
-

Returns

-

A list of invalid links of the specified type and format. If there are no invalid links, an empty list is returned.

-
- -Expand source code - -
def check_links_assets(self, num_links: int, url_type: str, format_type: str) -> List[str]:
-    """Checks the links and assets in the STAC catalog and returns a list of invalid links of a specified type and format.
-
-    Args:
-        num_links (int): The maximum number of invalid links to return.
-        url_type (str): The type of URL to check, which can be either 'self' or 'external'.
-        format_type (str): The format of the URL to check, which can be either 'html' or 'json'.
-
-    Returns:
-        A list of invalid links of the specified type and format. If there are no invalid links, an empty list is returned.
-    """
-    links = []
-    if f"{url_type}_validated" in self.message:
-        for invalid_request_url in self.message[f"{url_type}_validated"][f"{format_type}_invalid"]:
-            if invalid_request_url not in links and 'http' in invalid_request_url:
-                links.append(invalid_request_url)
-            num_links = num_links - 1
-            if num_links == 0:
-                return links
-    return links
-
-
- -
-

Checks whether the "self" link is present in the STAC collection or catalog or absent in STAC item.

-

Returns

-
-
bool
-
True if the "self" link is present in STAC collection or catalog or absent in STAC item, False otherwise.
-
-
- -Expand source code - -
def check_links_self(self) -> bool:
-    """Checks whether the "self" link is present in the STAC collection or catalog or absent in STAC item.
-    
-    Returns:
-        bool: True if the "self" link is present in STAC collection or catalog or absent in STAC item, False otherwise.
-    """
-    if self.asset_type == "ITEM":
-        return True
-    if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG":
-        for link in self.data["links"]:
-            if "self" in link["rel"]:
-                return True
-    return False
-
-
- -
-

Checks if all links in a STAC collection or catalog have a 'title' field. -The 'title' field is not required for the 'self' link.

-

Returns

-
-
bool
-
True if all links have a 'title' field, False otherwise.
-
-
- -Expand source code - -
def check_links_title_field(self) -> bool:
-    """Checks if all links in a STAC collection or catalog have a 'title' field.
-    The 'title' field is not required for the 'self' link.
-
-    Returns:
-        bool: True if all links have a 'title' field, False otherwise.
-    """
-    if self.asset_type == "COLLECTION" or self.asset_type == "CATALOG":
-        for link in self.data["links"]:
-            if "title" not in link and link["rel"] != "self":
-                return False
-    return True
-
-
-
-def check_percent_encoded(self) ‑> bool -
-
-

Checks if the identifiers of a STAC item are percent-encoded, i.e., + +

Returns: + str: A string containing the error type of a STAC validation if it exists in the validation message, and an + empty string otherwise.

+
+ + + +
+ +
+ + def + check_error_message(self) -> str: + + + +
+ +
369    def check_error_message(self) -> str:
+370        """Checks whether the `message` attribute contains an `error_message` field.
+371
+372        Returns:
+373            A string containing the value of the `error_message` field, or an empty string if the field is not present.
+374        """
+375        if "error_message" in self.message:
+376            return self.message["error_message"]
+377        else:
+378            return ""
+
+ + +

Checks whether the message attribute contains an error_message field.

+ +

Returns: + A string containing the value of the error_message field, or an empty string if the field is not present.

+
+ + +
+
+ +
+ + def + check_summaries(self) -> bool: + + + +
+ +
380    def check_summaries(self) -> bool:
+381        """Check if a Collection asset has a "summaries" property.
+382
+383        Returns:
+384            A boolean indicating whether the Collection asset has a "summaries" property.
+385        """
+386        if self.asset_type == "COLLECTION":
+387            return "summaries" in self.data
+388        else:
+389            return False
+
+ + +

Check if a Collection asset has a "summaries" property.

+ +

Returns: + A boolean indicating whether the Collection asset has a "summaries" property.

+
+ + +
+ +
+ +
+ + def + check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool: + + + +
+ +
405    def check_bloated_metadata(self, max_properties: Optional[int] = 20) -> bool:
+406        """Checks whether a STAC item's metadata contains too many properties.
+407
+408        Args:
+409            max_properties (int, optional): The maximum number of properties that the metadata can contain before it is
+410                considered too bloated. Defaults to 20.
+411
+412        Returns:
+413            bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by
+414                `max_properties`, False otherwise.
+415        """
+416        if "properties" in self.data:
+417            return len(self.data["properties"].keys()) > max_properties
+418        return False
+
+ + +

Checks whether a STAC item's metadata contains too many properties.

+ +

Args: + max_properties (int, optional): The maximum number of properties that the metadata can contain before it is + considered too bloated. Defaults to 20.

+ +

Returns: + bool: True if the number of properties in the metadata exceeds the maximum number of properties specified by + max_properties, False otherwise.

+
+ + +
+
+ +
+ + def + check_datetime_null(self) -> bool: + + + +
+ +
420    def check_datetime_null(self) -> bool:
+421        """Checks if the STAC item has a null datetime property.
+422
+423        Returns:
+424            bool: A boolean indicating whether the datetime property is null (True) or not (False).
+425        """
+426        if "properties" in self.data:
+427            if "datetime" in self.data["properties"]:
+428                if self.data["properties"]["datetime"] is None:
+429                    return True
+430        else:
+431            return False
+432        return False
+
+ + +

Checks if the STAC item has a null datetime property.

+ +

Returns: + bool: A boolean indicating whether the datetime property is null (True) or not (False).

+
+ + +
+
+ +
+ + def + check_unlocated(self) -> bool: + + + +
+ +
434    def check_unlocated(self) -> bool:
+435        """Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.
+436
+437        Returns:
+438            bool: True if the STAC item is unlocated, False otherwise.
+439        """
+440        if "geometry" in self.data:
+441            return self.data["geometry"] is None and self.data["bbox"] is not None
+442        else:
+443            return False
+
+ + +

Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.

+ +

Returns: + bool: True if the STAC item is unlocated, False otherwise.

+
+ + +
+
+ +
+ + def + check_geometry_null(self) -> bool: + + + +
+ +
445    def check_geometry_null(self) -> bool:
+446        """Checks if a STAC item has a null geometry property.
+447
+448        Returns:
+449            bool: A boolean indicating whether the geometry property is null (True) or not (False).
+450        """
+451        if "geometry" in self.data:
+452            return self.data["geometry"] is None
+453        else:
+454            return False
+
+ + +

Checks if a STAC item has a null geometry property.

+ +

Returns: + bool: A boolean indicating whether the geometry property is null (True) or not (False).

+
+ + +
+
+ +
+ + def + check_searchable_identifiers(self) -> bool: + + + +
+ +
456    def check_searchable_identifiers(self) -> bool:
+457        """Checks if the identifiers of a STAC item are searchable, i.e.,
+458        they only contain lowercase letters, numbers, hyphens, and underscores.
+459
+460        Returns:
+461            bool: True if the identifiers are searchable, False otherwise.
+462        """
+463        if self.asset_type == "ITEM":
+464            for letter in self.object_id:
+465                if (
+466                    letter.islower()
+467                    or letter.isnumeric()
+468                    or letter == "-"
+469                    or letter == "_"
+470                ):
+471                    pass
+472                else:
+473                    return False
+474        return True
+
+ + +

Checks if the identifiers of a STAC item are searchable, i.e., they only contain lowercase letters, numbers, hyphens, and underscores.

-

Returns

-
-
bool
-
True if the identifiers are percent-encoded, False otherwise.
-
-
- -Expand source code - -
def check_percent_encoded(self) -> bool:
-    """Checks if the identifiers of a STAC item are percent-encoded, i.e.,
-    they only contain lowercase letters, numbers, hyphens, and underscores.
-
-    Returns:
-        bool: True if the identifiers are percent-encoded, False otherwise.
-    """
-    return self.asset_type == "ITEM" and "/" in self.object_id or ":" in self.object_id
-
-
-
-def check_searchable_identifiers(self) ‑> bool -
-
-

Checks if the identifiers of a STAC item are searchable, i.e., + +

Returns: + bool: True if the identifiers are searchable, False otherwise.

+
+ + + +
+ +
+ + def + check_percent_encoded(self) -> bool: + + + +
+ +
476    def check_percent_encoded(self) -> bool:
+477        """Checks if the identifiers of a STAC item are percent-encoded, i.e.,
+478        they only contain lowercase letters, numbers, hyphens, and underscores.
+479
+480        Returns:
+481            bool: True if the identifiers are percent-encoded, False otherwise.
+482        """
+483        return (
+484            self.asset_type == "ITEM" and "/" in self.object_id or ":" in self.object_id
+485        )
+
+ + +

Checks if the identifiers of a STAC item are percent-encoded, i.e., they only contain lowercase letters, numbers, hyphens, and underscores.

-

Returns

-
-
bool
-
True if the identifiers are searchable, False otherwise.
-
-
- -Expand source code - -
def check_searchable_identifiers(self) -> bool:
-    """Checks if the identifiers of a STAC item are searchable, i.e., 
-    they only contain lowercase letters, numbers, hyphens, and underscores.
-    
-    Returns:
-        bool: True if the identifiers are searchable, False otherwise.        
-    """
-    if self.asset_type == "ITEM": 
-        for letter in self.object_id:
-            if letter.islower() or letter.isnumeric() or letter == '-' or letter == '_':
-                pass
-            else:
-                return False  
-    return True
-
-
-
-def check_summaries(self) ‑> bool -
-
-

Check if a Collection asset has a "summaries" property.

-

Returns

-

A boolean indicating whether the Collection asset has a "summaries" property.

-
- -Expand source code - -
def check_summaries(self) -> bool:
-    """Check if a Collection asset has a "summaries" property.
-
-    Returns:
-        A boolean indicating whether the Collection asset has a "summaries" property.
-    """
-    if self.asset_type == "COLLECTION":
-        return "summaries" in self.data
-
-
-
-def check_thumbnail(self) ‑> bool -
-
-

Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format.

-

Returns

-
-
bool
-
True if the thumbnail is valid, False otherwise.
-
-
- -Expand source code - -
def check_thumbnail(self) -> bool:
-    """Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format.
+
+

Returns: + bool: True if the identifiers are percent-encoded, False otherwise.

+ + + + +
+ +
+ + def + check_thumbnail(self) -> bool: + + + +
+ +
487    def check_thumbnail(self) -> bool:
+488        """Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format.
+489
+490        Returns:
+491            bool: True if the thumbnail is valid, False otherwise.
+492        """
+493        if "assets" in self.data:
+494            if "thumbnail" in self.data["assets"]:
+495                if "type" in self.data["assets"]["thumbnail"]:
+496                    if (
+497                        "png" in self.data["assets"]["thumbnail"]["type"]
+498                        or "jpeg" in self.data["assets"]["thumbnail"]["type"]
+499                        or "jpg" in self.data["assets"]["thumbnail"]["type"]
+500                        or "webp" in self.data["assets"]["thumbnail"]["type"]
+501                    ):
+502                        return True
+503                    else:
+504                        return False
+505        return True
+
+ + +

Checks if the thumbnail of a STAC item is valid, i.e., it has a valid format.

+ +

Returns: + bool: True if the thumbnail is valid, False otherwise.

+
+ + +
+ + +
+ +
+ + def + check_item_id_file_name(self) -> bool: + + + +
+ +
534    def check_item_id_file_name(self) -> bool:
+535        if self.asset_type == "ITEM" and self.object_id != self.file_name:
+536            return False
+537        else:
+538            return True
+
+ + - Returns: - bool: True if the thumbnail is valid, False otherwise. - """ - if "assets" in self.data: - if "thumbnail" in self.data["assets"]: - if "type" in self.data["assets"]["thumbnail"]: - if "png" in self.data["assets"]["thumbnail"]["type"] or "jpeg" in self.data["assets"]["thumbnail"]["type"] or \ - "jpg" in self.data["assets"]["thumbnail"]["type"] or "webp" in self.data["assets"]["thumbnail"]["type"]: - return True - else: - return False - return True
-
-
-
-def check_unlocated(self) ‑> bool -
-
-

Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.

-

Returns

-
-
bool
-
True if the STAC item is unlocated, False otherwise.
-
-
- -Expand source code - -
def check_unlocated(self) -> bool:
-    """Checks if a STAC item is unlocated, i.e., has no geometry but has a bounding box.
-
-    Returns:
-        bool: True if the STAC item is unlocated, False otherwise.
-    """
-    if "geometry" in self.data:
-        return self.data["geometry"] is None and self.data["bbox"] is not None
-
-
-
-def create_best_practices_dict(self) ‑> Dict -
-
-

Creates a dictionary of best practices violations for the current STAC object. The violations are determined + +

+
+ +
+ + def + check_catalog_file_name(self) -> bool: + + + +
+ +
540    def check_catalog_file_name(self) -> bool:
+541        """Checks whether the filename of a Catalog or Collection conforms to the STAC specification.
+542
+543        Returns:
+544            bool: True if the filename is valid, False otherwise.
+545        """
+546        if isinstance(self.item, str) and ".json" in self.item:
+547            if self.asset_type == "CATALOG" and "catalog.json" not in self.item:
+548                return False
+549            elif self.asset_type == "COLLECTION" and "collection.json" not in self.item:
+550                return False
+551            return True
+552        else:
+553            return True
+
+ + +

Checks whether the filename of a Catalog or Collection conforms to the STAC specification.

+ +

Returns: + bool: True if the filename is valid, False otherwise.

+
+ + +
+
+ +
+ + def + create_best_practices_dict(self) -> Dict: + + + +
+ +
555    def create_best_practices_dict(self) -> Dict:
+556        """Creates a dictionary of best practices violations for the current STAC object. The violations are determined
+557        by a set of configurable linting rules specified in the config file.
+558
+559        Returns:
+560            A dictionary of best practices violations for the current STAC object. The keys in the dictionary correspond
+561            to the linting rules that were violated, and the values are lists of strings containing error messages and
+562            recommendations for how to fix the violations.
+563        """
+564        best_practices_dict = {}
+565        config = self.config["linting"]
+566        max_links = self.config["settings"]["max_links"]
+567        max_properties = self.config["settings"]["max_properties"]
+568
+569        # best practices - item ids should only contain searchable identifiers
+570        if (
+571            self.check_searchable_identifiers() == False
+572            and config["searchable_identifiers"] == True
+573        ):
+574            msg_1 = f"Item name '{self.object_id}' should only contain Searchable identifiers"
+575            msg_2 = "Identifiers should consist of only lowercase characters, numbers, '_', and '-'"
+576            best_practices_dict["searchable_identifiers"] = [msg_1, msg_2]
+577
+578        # best practices - item ids should not contain ':' or '/' characters
+579        if self.check_percent_encoded() and config["percent_encoded"] == True:
+580            msg_1 = f"Item name '{self.object_id}' should not contain ':' or '/'"
+581            msg_2 = "https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#item-ids"
+582            best_practices_dict["percent_encoded"] = [msg_1, msg_2]
+583
+584        # best practices - item ids should match file names
+585        if not self.check_item_id_file_name() and config["item_id_file_name"] == True:
+586            msg_1 = f"Item file names should match their ids: '{self.file_name}' not equal to '{self.object_id}"
+587            best_practices_dict["check_item_id"] = [msg_1]
+588
+589        # best practices - collection and catalog file names should be collection.json and catalog.json
+590        if (
+591            self.check_catalog_file_name() == False
+592            and config["catalog_id_file_name"] == True
+593        ):
+594            msg_1 = f"Object should be called '{self.asset_type.lower()}.json' not '{self.file_name}.json'"
+595            best_practices_dict["check_catalog_id"] = [msg_1]
+596
+597        # best practices - collections should contain summaries
+598        if self.check_summaries() == False and config["check_summaries"] == True:
+599            msg_1 = "A STAC collection should contain a summaries field"
+600            msg_2 = "It is recommended to store information like eo:bands in summaries"
+601            best_practices_dict["check_summaries"] = [msg_1, msg_2]
+602
+603        # best practices - datetime fields should not be set to null
+604        if self.check_datetime_null() and config["null_datetime"] == True:
+605            msg_1 = "Please avoid setting the datetime field to null, many clients search on this field"
+606            best_practices_dict["datetime_null"] = [msg_1]
+607
+608        # best practices - check unlocated items to make sure bbox field is not set
+609        if self.check_unlocated() and config["check_unlocated"] == True:
+610            msg_1 = "Unlocated item. Please avoid setting the bbox field when geometry is set to null"
+611            best_practices_dict["check_unlocated"] = [msg_1]
+612
+613        # best practices - recommend items have a geometry
+614        if self.check_geometry_null() and config["check_geometry"] == True:
+615            msg_1 = "All items should have a geometry field. STAC is not meant for non-spatial data"
+616            best_practices_dict["null_geometry"] = [msg_1]
+617
+618        # check to see if there are too many links
+619        if (
+620            self.check_bloated_links(max_links=max_links)
+621            and config["bloated_links"] == True
+622        ):
+623            msg_1 = f"You have {len(self.data['links'])} links. Please consider using sub-collections or sub-catalogs"
+624            best_practices_dict["bloated_links"] = [msg_1]
+625
+626        # best practices - check for bloated metadata in properties
+627        if (
+628            self.check_bloated_metadata(max_properties=max_properties)
+629            and config["bloated_metadata"] == True
+630        ):
+631            msg_1 = f"You have {len(self.data['properties'])} properties. Please consider using links to avoid bloated metadata"
+632            best_practices_dict["bloated_metadata"] = [msg_1]
+633
+634        # best practices - ensure thumbnail is a small file size ["png", "jpeg", "jpg", "webp"]
+635        if (
+636            not self.check_thumbnail()
+637            and self.asset_type == "ITEM"
+638            and config["check_thumbnail"] == True
+639        ):
+640            msg_1 = "A thumbnail should have a small file size ie. png, jpeg, jpg, webp"
+641            best_practices_dict["check_thumbnail"] = [msg_1]
+642
+643        # best practices - ensure that links in catalogs and collections include a title field
+644        if not self.check_links_title_field() and config["links_title"] == True:
+645            msg_1 = (
+646                "Links in catalogs and collections should always have a 'title' field"
+647            )
+648            best_practices_dict["check_links_title"] = [msg_1]
+649
+650        # best practices - ensure that links in catalogs and collections include self link
+651        if not self.check_links_self() and config["links_self"] == True:
+652            msg_1 = "A link to 'self' in links is strongly recommended"
+653            best_practices_dict["check_links_self"] = [msg_1]
+654
+655        return best_practices_dict
+
+ + +

Creates a dictionary of best practices violations for the current STAC object. The violations are determined by a set of configurable linting rules specified in the config file.

-

Returns

-

A dictionary of best practices violations for the current STAC object. The keys in the dictionary correspond -to the linting rules that were violated, and the values are lists of strings containing error messages and -recommendations for how to fix the violations.

-
- -Expand source code - -
def create_best_practices_dict(self) -> Dict:
-    """Creates a dictionary of best practices violations for the current STAC object. The violations are determined
-    by a set of configurable linting rules specified in the config file.
-
-    Returns:
-        A dictionary of best practices violations for the current STAC object. The keys in the dictionary correspond
-        to the linting rules that were violated, and the values are lists of strings containing error messages and
-        recommendations for how to fix the violations.
-    """
-    best_practices_dict = {}
-    config = self.config["linting"]
-    max_links = self.config["settings"]["max_links"]
-    max_properties = self.config["settings"]["max_properties"]
-
-    # best practices - item ids should only contain searchable identifiers
-    if self.check_searchable_identifiers() == False and config["searchable_identifiers"] == True: 
-        msg_1 = f"Item name '{self.object_id}' should only contain Searchable identifiers"
-        msg_2 = f"Identifiers should consist of only lowercase characters, numbers, '_', and '-'"
-        best_practices_dict["searchable_identifiers"] = [msg_1, msg_2]
-
-    # best practices - item ids should not contain ':' or '/' characters
-    if self.check_percent_encoded() and config["percent_encoded"] == True:
-        msg_1 = f"Item name '{self.object_id}' should not contain ':' or '/'"
-        msg_2 = f"https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#item-ids"
-        best_practices_dict["percent_encoded"] = [msg_1, msg_2]
-
-    # best practices - item ids should match file names
-    if not self.check_item_id_file_name() and config["item_id_file_name"] == True:
-        msg_1 = f"Item file names should match their ids: '{self.file_name}' not equal to '{self.object_id}"
-        best_practices_dict["check_item_id"] = [msg_1]
-
-    # best practices - collection and catalog file names should be collection.json and catalog.json 
-    if self.check_catalog_file_name() == False and config["catalog_id_file_name"] == True: 
-        msg_1 = f"Object should be called '{self.asset_type.lower()}.json' not '{self.file_name}.json'"
-        best_practices_dict["check_catalog_id"] = [msg_1]
-
-    # best practices - collections should contain summaries
-    if self.check_summaries() == False and config["check_summaries"] == True:
-        msg_1 = f"A STAC collection should contain a summaries field"
-        msg_2 = f"It is recommended to store information like eo:bands in summaries"
-        best_practices_dict["check_summaries"] = [msg_1, msg_2]
-
-    # best practices - datetime fields should not be set to null
-    if self.check_datetime_null() and config["null_datetime"] == True:
-        msg_1 = f"Please avoid setting the datetime field to null, many clients search on this field"
-        best_practices_dict["datetime_null"] = [msg_1]
-
-    # best practices - check unlocated items to make sure bbox field is not set
-    if self.check_unlocated() and config["check_unlocated"] == True:
-        msg_1 = f"Unlocated item. Please avoid setting the bbox field when geometry is set to null"
-        best_practices_dict["check_unlocated"] = [msg_1]
-
-    # best practices - recommend items have a geometry
-    if self.check_geometry_null() and config["check_geometry"] == True:
-        msg_1 = f"All items should have a geometry field. STAC is not meant for non-spatial data"
-        best_practices_dict["null_geometry"] = [msg_1]
-
-    # check to see if there are too many links
-    if self.check_bloated_links(max_links=max_links) and config["bloated_links"] == True:
-        msg_1 = f"You have {len(self.data['links'])} links. Please consider using sub-collections or sub-catalogs"
-        best_practices_dict["bloated_links"] = [msg_1]
-
-    # best practices - check for bloated metadata in properties
-    if self.check_bloated_metadata(max_properties=max_properties) and config["bloated_metadata"] == True:
-        msg_1 = f"You have {len(self.data['properties'])} properties. Please consider using links to avoid bloated metadata"
-        best_practices_dict["bloated_metadata"] = [msg_1]
-
-    # best practices - ensure thumbnail is a small file size ["png", "jpeg", "jpg", "webp"]
-    if not self.check_thumbnail() and self.asset_type == "ITEM" and config["check_thumbnail"] == True:
-        msg_1 = f"A thumbnail should have a small file size ie. png, jpeg, jpg, webp"
-        best_practices_dict["check_thumbnail"] = [msg_1]
-
-    # best practices - ensure that links in catalogs and collections include a title field
-    if not self.check_links_title_field() and config["links_title"] == True:
-        msg_1 = f"Links in catalogs and collections should always have a 'title' field"
-        best_practices_dict["check_links_title"] = [msg_1]
-
-    # best practices - ensure that links in catalogs and collections include self link
-    if not self.check_links_self() and config["links_self"] == True:
-        msg_1 = f"A link to 'self' in links is strongly recommended"
-        best_practices_dict["check_links_self"] = [msg_1]
-
-    return best_practices_dict
-
-
-
-def create_best_practices_msg(self) ‑> List[str] -
-
-

Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method.

-

Returns

-

A list of strings, where each string contains a best practice message. Each message starts with the -'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented -with four spaces, and there is an empty string between each message for readability.

-
- -Expand source code - -
def create_best_practices_msg(self) -> List[str]:
-    """
-    Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method.
-
-    Returns:
-        A list of strings, where each string contains a best practice message. Each message starts with the 
-        'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented 
-        with four spaces, and there is an empty string between each message for readability.
-    """
-    best_practices = list()
-    base_string = "STAC Best Practices: "
-    best_practices.append(base_string)
-
-    for _,v in self.create_best_practices_dict().items():
-        for value in v:
-            best_practices.extend(["    " +value])  
-        best_practices.extend([""])
-
-    return best_practices
-
-
-
-def get_asset_name(self, file: Union[str, Dict] = None) ‑> str -
-
-

Extracts the name of an asset from its file path or from a STAC item asset dictionary.

-

Args

-
-
file : Union[str, dict], optional
-
A string representing the file path to the asset or a dictionary representing the -asset as specified in a STAC item's assets property.
-
-

Returns

-

A string containing the name of the asset.

-

Raises

-
-
TypeError
-
If the input file is not a string or a dictionary.
-
-
- -Expand source code - -
def get_asset_name(self, file: Union[str, Dict] = None) -> str:
-    """Extracts the name of an asset from its file path or from a STAC item asset dictionary.
-
-    Args:
-        file (Union[str, dict], optional): A string representing the file path to the asset or a dictionary representing the
-            asset as specified in a STAC item's `assets` property.
-
-    Returns:
-        A string containing the name of the asset.
-
-    Raises:
-        TypeError: If the input `file` is not a string or a dictionary.
-    """
-    if isinstance(file, str):
-        return os.path.basename(file).split('.')[0]
-    else:
-        return file["id"]
-
-
-
-def load_data(self, file: Union[str, Dict]) ‑> Dict -
-
-

Loads JSON data from a file or URL.

-

Args

-
-
file : Union[str, Dict]
-
A string representing the path to a JSON file or a dictionary containing the JSON data.
-
-

Returns

-

A dictionary containing the loaded JSON data.

-

Raises

-
-
TypeError
-
If the input file is not a string or dictionary.
-
ValueError
-
If file is a string that doesn't represent a valid URL or file path.
-
requests.exceptions.RequestException
-
If there is an error making a request to a URL.
-
JSONDecodeError
-
If the JSON data cannot be decoded.
-
FileNotFoundError
-
If the specified file cannot be found.
-
-
- -Expand source code - -
def load_data(self, file: Union[str, Dict]) -> Dict:
-    """Loads JSON data from a file or URL.
-
-    Args:
-        file (Union[str, Dict]): A string representing the path to a JSON file or a dictionary containing the JSON data.
-
-    Returns:
-        A dictionary containing the loaded JSON data.
-
-    Raises:
-        TypeError: If the input `file` is not a string or dictionary.
-        ValueError: If `file` is a string that doesn't represent a valid URL or file path.
-        requests.exceptions.RequestException: If there is an error making a request to a URL.
-        JSONDecodeError: If the JSON data cannot be decoded.
-        FileNotFoundError: If the specified file cannot be found.
-    """
-
-    if isinstance(file, str):
-        if is_valid_url(file):
-            resp = requests.get(file)
-            data = resp.json()
-        else:
-            with open(file) as json_file:
-                data = json.load(json_file)
-        return data
-    else:
-        return file
-
-
-
-def recursive_validation(self, file: Union[str, Dict[str, Any]]) ‑> str -
-
-

Recursively validate a STAC item or catalog file and its child items.

-

Args

-
-
file : Union[str, Dict[str, Any]]
-
A string representing the file path to the STAC item or catalog, or a -dictionary representing the STAC item or catalog.
-
-

Returns

-

A string containing the validation message.

-

Raises

-
-
TypeError
-
If the input file is not a string or a dictionary.
-
-
- -Expand source code - -
def recursive_validation(self, file: Union[str, Dict[str, Any]]) -> str:
-    """Recursively validate a STAC item or catalog file and its child items.
-
-    Args:
-        file (Union[str, Dict[str, Any]]): A string representing the file path to the STAC item or catalog, or a
-            dictionary representing the STAC item or catalog.
-
-    Returns:
-        A string containing the validation message.
-
-    Raises:
-        TypeError: If the input `file` is not a string or a dictionary.
-    """
-    if self.recursive:
-        if isinstance(file, str):
-            stac = StacValidate(file, recursive=True, max_depth=self.max_depth)
-            stac.run()
-        else:
-            stac = StacValidate(recursive=True, max_depth=self.max_depth)
-            stac.validate_dict(file)
-        return stac.message
-
-
-
-def set_update_message(self) ‑> str -
-
-

Returns a message for users to update their STAC version.

-

Returns

-

A string containing a message for users to update their STAC version.

-
- -Expand source code - -
def set_update_message(self) -> str:
-    """Returns a message for users to update their STAC version.
-
-    Returns:
-        A string containing a message for users to update their STAC version.
-    """
-    if self.version != "1.0.0":
-        return f"Please upgrade from version {self.version} to version 1.0.0!"
-    else:
-        return "Thanks for using STAC version 1.0.0!"
-
-
-
-def validate_file(self, file: Union[str, dict]) ‑> Dict[str, Any] -
-
-

Validates the given file path or STAC dictionary against the validation schema.

-

Args

-
-
file : Union[str, dict]
-
A string representing the file path to the STAC file or a dictionary representing the STAC -item.
-
-

Returns

-

A dictionary containing the results of the validation, including the status of the validation and any errors -encountered.

-

Raises

-
-
ValueError
-
If file is not a valid file path or STAC dictionary.
-
-
- -Expand source code - -
def validate_file(self, file: Union[str, dict]) -> Dict[str, Any]:
-    """Validates the given file path or STAC dictionary against the validation schema.
-
-    Args:
-        file (Union[str, dict]): A string representing the file path to the STAC file or a dictionary representing the STAC
-            item.
-
-    Returns:
-        A dictionary containing the results of the validation, including the status of the validation and any errors
-        encountered.
-
-    Raises:
-        ValueError: If `file` is not a valid file path or STAC dictionary.
-    """
-    if isinstance(file, str):
-        stac = StacValidate(file, links=self.links, assets=self.assets)
-        stac.run()
-    elif isinstance(file, dict):
-        stac = StacValidate()
-        stac.validate_dict(file)
-    else:
-        raise ValueError("Input must be a file path or STAC dictionary.")
-    return stac.message[0]
-
-
-
-
-
-
-
- -
- - + + + +
+ +
+ + def + create_best_practices_msg(self) -> List[str]: + + + +
+ +
657    def create_best_practices_msg(self) -> List[str]:
+658        """
+659        Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method.
+660
+661        Returns:
+662            A list of strings, where each string contains a best practice message. Each message starts with the
+663            'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented
+664            with four spaces, and there is an empty string between each message for readability.
+665        """
+666        best_practices = list()
+667        base_string = "STAC Best Practices: "
+668        best_practices.append(base_string)
+669
+670        for _, v in self.create_best_practices_dict().items():
+671            for value in v:
+672                best_practices.extend(["    " + value])
+673            best_practices.extend([""])
+674
+675        return best_practices
+
+ + +

Generates a list of best practices messages based on the results of the 'create_best_practices_dict' method.

+ +

Returns: + A list of strings, where each string contains a best practice message. Each message starts with the + 'STAC Best Practices:' base string and is followed by a specific recommendation. Each message is indented + with four spaces, and there is an empty string between each message for readability.

+
+ + +
+ + + \ No newline at end of file diff --git a/pdoc/stac_check/logo.html b/pdoc/stac_check/logo.html new file mode 100644 index 0000000..d7ceee1 --- /dev/null +++ b/pdoc/stac_check/logo.html @@ -0,0 +1,265 @@ + + + + + + + stac_check.logo API documentation + + + + + + + + + +
+
+

+stac_check.logo

+ + + + + + +
1# flake8: noqa
+2
+3logo = r"""
+4 ____  ____  __    ___       ___  _  _  ____  ___  __ _ 
+5/ ___)(_  _)/ _\  / __)___  / __)/ )( \(  __)/ __)(  / )
+6\___ \  )( /    \( (__(___)( (__ ) __ ( ) _)( (__  )  ( 
+7(____/ (__)\_/\_/ \___)     \___)\_)(_/(____)\___)(__\_)
+8    """
+
+ + +
+ +
+ + \ No newline at end of file From a5dea8716133cc990beef17ffe2066912218341f Mon Sep 17 00:00:00 2001 From: Vincent Privat Date: Mon, 13 Jan 2025 17:02:11 +0100 Subject: [PATCH 4/4] Add tests --- setup.py | 1 + tests/test_lint.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/setup.py b/setup.py index 648db1f..facae45 100644 --- a/setup.py +++ b/setup.py @@ -27,6 +27,7 @@ extras_require={ "dev": [ "pytest", + "requests-mock", "types-setuptools", ], }, diff --git a/tests/test_lint.py b/tests/test_lint.py index 8b038d0..f7d5149 100644 --- a/tests/test_lint.py +++ b/tests/test_lint.py @@ -1,4 +1,7 @@ +import json + import pytest +import requests_mock from stac_check.lint import Linter @@ -498,3 +501,65 @@ def test_lint_dict_item(): assert linter.create_best_practices_dict()["datetime_null"] == [ "Please avoid setting the datetime field to null, many clients search on this field" ] + + +def test_lint_header(): + file = "sample_files/1.0.0/core-item.json" + url = "https://localhost/" + file + + no_headers = {} + valid_headers = {"x-api-key": "a-valid-api-key"} + + with requests_mock.Mocker(real_http=True) as mock, open(file) as json_data: + mock.get(url, request_headers=no_headers, status_code=403, json={}) + mock.get(url, request_headers=valid_headers, json=json.load(json_data)) + + linter = Linter(url, assets=False, headers=valid_headers) + assert linter.message == { + "version": "1.0.0", + "path": "https://localhost/sample_files/1.0.0/core-item.json", + "schema": [ + "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json" + ], + "valid_stac": True, + "asset_type": "ITEM", + "validation_method": "default", + } + + linter = Linter(url, assets=False, headers=no_headers) + assert linter.message == { + "version": "", + "path": "https://localhost/sample_files/1.0.0/core-item.json", + "schema": [""], + "valid_stac": False, + "error_type": "HTTPError", + "error_message": "403 Client Error: None for url: https://localhost/sample_files/1.0.0/core-item.json", + } + + +def test_lint_assets_no_links(): + file = "sample_files/1.0.0/core-item.json" + linter = Linter(file, assets=True, assets_open_urls=False) + assert linter.message == { + "version": "1.0.0", + "path": file, + "schema": [ + "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json" + ], + "valid_stac": True, + "asset_type": "ITEM", + "validation_method": "default", + "assets_validated": { + "format_valid": [ + "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif", + "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg", + "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif", + "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic_udm.tif", + "http://remotedata.io/catalog/20201211_223832_CS2/extended-metadata.json", + "http://cool-sat.com/catalog/20201211_223832_CS2/20201211_223832_CS2.EPH", + ], + "format_invalid": [], + "request_valid": [], + "request_invalid": [], + }, + }