def test_validate_examples(self) -> None: for example in TestCases.get_examples_info(): with self.subTest(example.path): stac_version = example.stac_version path = example.path valid = example.valid with self.subTest(path): with open(path, encoding="utf-8") as f: stac_json = json.load(f) # Check if common properties need to be merged if stac_version < "1.0": if example.object_type == pystac.STACObjectType.ITEM: collection_cache = CollectionCache() merge_common_properties(stac_json, collection_cache, path) if valid: pystac.validation.validate_dict(stac_json) else: with self.assertRaises(pystac.STACValidationError): try: pystac.validation.validate_dict(stac_json) except pystac.STACValidationError as e: self.assertIsInstance( e.source, jsonschema.ValidationError) raise e
def test_validate_examples(self): for example in TestCases.get_examples_info(): stac_version = example['stac_version'] path = example['path'] valid = example['valid'] if stac_version < '0.8': with open(path) as f: stac_json = json.load(f) self.assertEqual( len(pystac.validation.validate_dict(stac_json)), 0) else: with self.subTest(path): with open(path) as f: stac_json = json.load(f) # Check if common properties need to be merged if stac_version < '1.0': if example[ 'object_type'] == pystac.STACObjectType.ITEM: collection_cache = pystac.cache.CollectionCache() merge_common_properties(stac_json, collection_cache, path) if valid: pystac.validation.validate_dict(stac_json) else: with self.assertRaises(STACValidationError): try: pystac.validation.validate_dict(stac_json) except STACValidationError as e: self.assertIsInstance( e.source, jsonschema.ValidationError) raise e
def stac_object_from_dict(d, href=None, root=None): """Determines how to deserialize a dictionary into a STAC object. Args: d (dict): The dict to parse. href (str): Optional href that is the file location of the object being parsed. root (Catalog or Collection): Optional root of the catalog for this object. If provided, the root's resolved object cache can be used to search for previously resolved instances of the STAC object. Note: This is used internally in STAC_IO to deserialize STAC Objects. It is in the top level __init__ in order to avoid circular dependencies. """ if identify_stac_object_type(d) == STACObjectType.ITEM: collection_cache = None if root is not None: collection_cache = root._resolved_objects.as_collection_cache() merge_common_properties(d, json_href=href, collection_cache=collection_cache) info = identify_stac_object(d) d = migrate_to_latest(d, info) if info.object_type == STACObjectType.CATALOG: return Catalog.from_dict(d, href=href, root=root) if info.object_type == STACObjectType.COLLECTION: return Collection.from_dict(d, href=href, root=root) if info.object_type == STACObjectType.ITEMCOLLECTION: if Extension.SINGLE_FILE_STAC in info.common_extensions: return SingleFileSTAC.from_dict(d, href=href, root=root) return ItemCollection.from_dict(d, href=href, root=root) if info.object_type == STACObjectType.ITEM: if Extension.EO in info.common_extensions: return EOItem.from_dict(d, href=href, root=root) if Extension.LABEL in info.common_extensions: return LabelItem.from_dict(d, href=href, root=root) return Item.from_dict(d, href=href, root=root)
def identify_stac_object(json_dict, merge_collection_properties=False, json_href=None, collection_cache=None): """Determines the STACJSONDescription of the provided JSON dict. Args: json_dict (dict): The dict of STAC JSON to identify. merge_collection_properties (bool): If True, follow the collection links in Items if required to discover extensions and version (pre-0.8 STAC). Defaults to False. json_href (str): The path that this JSON came from. This is useful for for resolving relative paths to Collections in the case that ``merge_collection_properties`` is True and the collection link is relative. collection_cache (dict): If supplied, collection read for item links will check this cache for either the collection's ID (if available) or the HREF of the collection link. This is recommended to reduce unnecessary re-reading of collections. Returns: STACJSONDescription: The description of the STAC object serialized in the given dict. Note: If ``merge_collection_properties`` is False, there are cases where the common_extensions returned could be incorrect - e.g. if a collection lists 'eo' extension properties but the Item does not contian any properties with the 'eo:' prefix. """ object_type = identify_stac_object_type(json_dict) version_range = STACVersionRange() stac_version = json_dict.get('stac_version') stac_extensions = json_dict.get('stac_extensions', None) if stac_version is None: if object_type == STACObjectType.CATALOG or object_type == STACObjectType.COLLECTION: version_range.set_max('0.5.2') elif object_type == STACObjectType.ITEM: version_range.set_max('0.7.0') else: # ItemCollection version_range.set_min('0.8.0') else: version_range.set_to_single(stac_version) if stac_extensions is None: # If this is post-0.8, we can assume there are no extensions # if the stac_extensions property doesn't exist for everything # but ItemCollection. if version_range.min_version is None or \ version_range.min_version < '0.8.0' or \ object_type == STACObjectType.ITEMCOLLECTION: if merge_collection_properties and object_type == STACObjectType.ITEM: merge_common_properties(json_dict, collection_cache, json_href) stac_extensions = _identify_stac_extensions( object_type, json_dict, version_range) else: stac_extensions = [] if not version_range.is_single_version(): # Final Checks # self links became non-required in 0.7.0 if 'links' in json_dict: if not any(filter(lambda l: l['rel'] == 'self', json_dict['links'])): version_range.set_min('0.7.0') # links were a dictionary only in 0.5 if 'links' in json_dict and isinstance(json_dict['links'], dict): version_range.set_to_single('0.5.2') common_extensions, custom_extensions = _split_extensions(stac_extensions) return STACJSONDescription(object_type, version_range, common_extensions, custom_extensions)