Source code for pystac.validation.schema_uri_map

from abc import (ABC, abstractmethod)

import pystac
from pystac import (STACObjectType, Extensions)
from pystac.serialization import STACVersionRange


[docs]class SchemaUriMap(ABC): """Abstract class defining schema URIs for STAC core objects and extensions. """ def __init__(self): pass
[docs] @abstractmethod def get_core_schema_uri(self, object_type, stac_version): """Get the schema URI for the given object type and stac version. Args: object_type (str): STAC object type. One of :class:`~pystac.STACObjectType` stac_version (str): The STAC version of the schema to return. Returns: str: The URI of the schema, or None if not found. """ pass
[docs] @abstractmethod def get_extension_schema_uri(self, extension_id, object_type, stac_version): """Get the extension's schema URI for the given object type, stac version. Args: extension_id (str): The Extension ID of the extension of the schema. object_type (str): STAC object type. One of :class:`~pystac.STACObjectType` stac_version (str): The STAC version of the schema to return. Returns: str: The URI of the schema, or None if not found. """ pass
[docs]class DefaultSchemaUriMap(SchemaUriMap): """Implementation of SchemaUriMap that uses schemas hosted by https://schemas.stacspec.org. For STAC Versions 0.9.0 or earlier this will use the schemas hosted on the radiantearth/stac-spec GitHub repo. """ # BASE_URIS contains a list of tuples, the first element is a version range and the # second being the base URI for schemas for that range. The schema URI of a STAC # for a particular version uses the base URI associated with the version range which # contains it. If the version it outside of any VersionRange, there is no URI for the # schema. BASE_URIS = [(STACVersionRange(min_version='1.0.0-beta.1'), lambda version: 'https://schemas.stacspec.org/v{}'.format(version)), (STACVersionRange(min_version='0.8.0', max_version='0.9.0'), lambda version: 'https://raw.githubusercontent.com/radiantearth/stac-spec/v{}'.format(version))] # DEFAULT_SCHEMA_MAP contains a structure that matches 'core' or 'extension' schema URIs # based on the stac object type and the stac version, using a similar technique as BASE_URIS. # Uris are contained in a tuple whose first element represents the URI of the latest # version, so that a search through version ranges is avoided if the STAC being validated # is the latest version. If it's a previous version, the stac_version that matches # the listed version range is used, or else the URI from the latest version is used if # there are no overrides for previous versions. DEFAULT_SCHEMA_MAP = { 'core': { STACObjectType.CATALOG: ('catalog-spec/json-schema/catalog.json', None), STACObjectType.COLLECTION: ('collection-spec/json-schema/collection.json', None), STACObjectType.ITEM: ('item-spec/json-schema/item.json', None), STACObjectType.ITEMCOLLECTION: (None, [ STACVersionRange(min_version='v0.8.0-rc1', max_version='0.9.0'), 'item-spec/json-schema/itemcollection.json' ]) }, 'extension': { Extensions.CHECKSUM: ({ STACObjectType.CATALOG: 'extensions/checksum/json-schema/schema.json', STACObjectType.COLLECTION: 'extensions/checksum/json-schema/schema.json', STACObjectType.ITEM: 'extensions/checksum/json-schema/schema.json' }, None), Extensions.COLLECTION_ASSETS: ({ STACObjectType.COLLECTION: 'extensions/collection-assets/json-schema/schema.json' }, None), Extensions.DATACUBE: ({ STACObjectType.COLLECTION: 'extensions/datacube/json-schema/schema.json', STACObjectType.ITEM: 'extensions/datacube/json-schema/schema.json' }, [(STACVersionRange(min_version='0.5.0', max_version='0.9.0'), { STACObjectType.COLLECTION: None, STACObjectType.ITEM: None })]), Extensions.EO: ({ STACObjectType.ITEM: 'extensions/eo/json-schema/schema.json' }, None), Extensions.ITEM_ASSETS: ({ STACObjectType.COLLECTION: 'extensions/item-assets/json-schema/schema.json' }, None), Extensions.LABEL: ({ STACObjectType.ITEM: 'extensions/label/json-schema/schema.json' }, [(STACVersionRange(min_version='0.8.0-rc1', max_version='0.8.1'), { STACObjectType.ITEM: 'extensions/label/schema.json' })]), Extensions.POINTCLOUD: ( { STACObjectType.ITEM: None # 'extensions/pointcloud/json-schema/schema.json' }, None), Extensions.PROJECTION: ({ STACObjectType.ITEM: 'extensions/projection/json-schema/schema.json' }, None), Extensions.SAR: ({ STACObjectType.ITEM: 'extensions/sar/json-schema/schema.json' }, None), Extensions.SAT: ({ STACObjectType.ITEM: 'extensions/sat/json-schema/schema.json' }, None), Extensions.SCIENTIFIC: ({ STACObjectType.ITEM: 'extensions/scientific/json-schema/schema.json', STACObjectType.COLLECTION: 'extensions/scientific/json-schema/schema.json' }, None), Extensions.SINGLE_FILE_STAC: ({ STACObjectType.CATALOG: 'extensions/single-file-stac/json-schema/schema.json' }, None), Extensions.TILED_ASSETS: ({ STACObjectType.CATALOG: 'extensions/tiled-assets/json-schema/schema.json', STACObjectType.COLLECTION: 'extensions/tiled-assets/json-schema/schema.json', STACObjectType.ITEM: 'extensions/tiled-assets/json-schema/schema.json' }, None), Extensions.TIMESTAMPS: ({ STACObjectType.ITEM: 'extensions/timestamps/json-schema/schema.json' }, None), Extensions.VERSION: ({ STACObjectType.ITEM: 'extensions/version/json-schema/schema.json', STACObjectType.COLLECTION: 'extensions/version/json-schema/schema.json' }, None), Extensions.VIEW: ({ STACObjectType.ITEM: 'extensions/view/json-schema/schema.json' }, None), # Removed or renamed extensions. 'dtr': (None, None), # Invalid schema 'asset': (None, [(STACVersionRange(min_version='0.8.0-rc1', max_version='0.9.0'), { STACObjectType.COLLECTION: 'extensions/asset/json-schema/schema.json' })]), } } @classmethod def _append_base_uri_if_needed(cls, uri, stac_version): # Only append the base URI if it's not already an absolute URI if '://' not in uri: base_uri = None for version_range, f in cls.BASE_URIS: if version_range.contains(stac_version): base_uri = f(stac_version) return '{}/{}'.format(base_uri, uri) # We don't have JSON schema validation for this version of PySTAC return None else: return uri
[docs] def get_core_schema_uri(self, object_type, stac_version): uri = None is_latest = stac_version == pystac.get_stac_version() if object_type not in self.DEFAULT_SCHEMA_MAP['core']: raise KeyError('Unknown STAC object type {}'.format(object_type)) uri = self.DEFAULT_SCHEMA_MAP['core'][object_type][0] if not is_latest: if self.DEFAULT_SCHEMA_MAP['core'][object_type][1]: for version_range, range_uri in self.DEFAULT_SCHEMA_MAP['core'][object_type][1]: if version_range.contains(stac_version): uri = range_uri break return self._append_base_uri_if_needed(uri, stac_version)
[docs] def get_extension_schema_uri(self, extension_id, object_type, stac_version): uri = None is_latest = stac_version == pystac.get_stac_version() ext_map = self.DEFAULT_SCHEMA_MAP['extension'] if extension_id in ext_map: if ext_map[extension_id][0] and \ object_type in ext_map[extension_id][0]: uri = ext_map[extension_id][0][object_type] if not is_latest: if ext_map[extension_id][1]: for version_range, ext_uris in ext_map[extension_id][1]: if version_range.contains(stac_version): if object_type in ext_uris: uri = ext_uris[object_type] break if uri is None: return uri else: return self._append_base_uri_if_needed(uri, stac_version)