Exemplo n.º 1
0
    def test_migrate(self):
        collection_cache = CollectionCache()
        for example in self.examples:
            path = example['path']
            d = STAC_IO.read_json(path)
            if identify_stac_object_type(d) == STACObjectType.ITEM:
                merge_common_properties(d,
                                        json_href=path,
                                        collection_cache=collection_cache)

            info = identify_stac_object(d)

            migrated_d = migrate_to_latest(d, info)

            migrated_info = identify_stac_object(migrated_d)

            self.assertEqual(migrated_info.object_type, info.object_type)
            self.assertEqual(
                migrated_info.version_range.latest_valid_version(),
                STAC_VERSION)
            self.assertEqual(set(migrated_info.common_extensions),
                             set(info.common_extensions))
            self.assertEqual(set(migrated_info.custom_extensions),
                             set(info.custom_extensions))

            # Test that PySTAC can read it without errors.
            self.assertIsInstance(
                STAC_IO.stac_object_from_dict(migrated_d, href=path),
                STACObject)
Exemplo n.º 2
0
    def test_migrate(self) -> None:
        collection_cache = CollectionCache()
        for example in self.examples:
            with self.subTest(example.path):
                path = example.path

                d = pystac.StacIO.default().read_json(path)
                if identify_stac_object_type(d) == pystac.STACObjectType.ITEM:
                    merge_common_properties(d,
                                            json_href=path,
                                            collection_cache=collection_cache)

                info = identify_stac_object(d)

                migrated_d = migrate_to_latest(d, info)

                migrated_info = identify_stac_object(migrated_d)

                self.assertEqual(migrated_info.object_type, info.object_type)
                self.assertEqual(
                    migrated_info.version_range.latest_valid_version(),
                    pystac.get_stac_version(),
                )

                # Ensure all stac_extensions are schema URIs
                for e_id in migrated_d["stac_extensions"]:
                    self.assertTrue(e_id.endswith(".json"),
                                    f"{e_id} is not a JSON schema URI")
Exemplo n.º 3
0
    def test_identify_non_stac_raises_error(self) -> None:
        plain_feature_dict = {
            "type": "Feature",
            "properties": {},
            "geometry": {"type": "Point", "coordinates": [0, 0]},
        }

        with self.assertRaises(pystac.STACTypeError) as ctx:
            identify_stac_object(plain_feature_dict)

        self.assertIn("JSON does not represent a STAC object", str(ctx.exception))
Exemplo n.º 4
0
    def stac_object_from_dict(
        self,
        d: Dict[str, Any],
        href: Optional[HREF] = None,
        root: Optional["Catalog_Type"] = None,
        preserve_dict: bool = True,
    ) -> "STACObject_Type":
        """Deserializes a :class:`~pystac.STACObject` sub-class instance from a
        dictionary.

        Args:

            d : The dictionary to deserialize
            href : Optional href to associate with the STAC object
            root : Optional root :class:`~pystac.Catalog` to associate with the
                STAC object.
            preserve_dict: If ``False``, the dict parameter ``d`` may be modified
                during this method call. Otherwise the dict is not mutated.
                Defaults to ``True``, which results results in a deepcopy of the
                parameter. Set to ``False`` when possible to avoid the performance
                hit of a deepcopy.
        """
        href_str = None if href is None else str(os.fspath(href))
        if identify_stac_object_type(d) == pystac.STACObjectType.ITEM:
            collection_cache = None
            if root is not None:
                collection_cache = root._resolved_objects.as_collection_cache()

            # Merge common properties in case this is an older STAC object.
            merge_common_properties(d,
                                    json_href=href_str,
                                    collection_cache=collection_cache)

        info = identify_stac_object(d)
        d = migrate_to_latest(d, info)

        if info.object_type == pystac.STACObjectType.CATALOG:
            result = pystac.Catalog.from_dict(d,
                                              href=href_str,
                                              root=root,
                                              migrate=False,
                                              preserve_dict=preserve_dict)
            result._stac_io = self
            return result

        if info.object_type == pystac.STACObjectType.COLLECTION:
            return pystac.Collection.from_dict(d,
                                               href=href_str,
                                               root=root,
                                               migrate=False,
                                               preserve_dict=preserve_dict)

        if info.object_type == pystac.STACObjectType.ITEM:
            return pystac.Item.from_dict(d,
                                         href=href_str,
                                         root=root,
                                         migrate=False,
                                         preserve_dict=preserve_dict)

        raise ValueError(f"Unknown STAC object type {info.object_type}")
Exemplo n.º 5
0
    def test_identify(self):
        collection_cache = {}
        for example in self.examples:
            path = example['path']
            d = STAC_IO.read_json(path)

            actual = identify_stac_object(d,
                                          merge_collection_properties=True,
                                          json_href=path,
                                          collection_cache=collection_cache)

            msg = 'Failed {}:'.format(path)

            self.assertEqual(actual.object_type,
                             example['object_type'],
                             msg=msg)
            version_contained_in_range = actual.version_range.contains(
                example['stac_version'])
            self.assertTrue(version_contained_in_range, msg=msg)
            self.assertEqual(set(actual.common_extensions),
                             set(example['common_extensions']),
                             msg=msg)
            self.assertEqual(set(actual.custom_extensions),
                             set(example['custom_extensions']),
                             msg=msg)
Exemplo n.º 6
0
    def from_dict(
        cls,
        d: Dict[str, Any],
        href: Optional[str] = None,
        root: Optional[Catalog] = None,
        migrate: bool = False,
        preserve_dict: bool = True,
    ) -> "Item":
        if migrate:
            info = identify_stac_object(d)
            d = migrate_to_latest(d, info)

        if not cls.matches_object_type(d):
            raise pystac.STACTypeError(
                f"{d} does not represent a {cls.__name__} instance")

        if preserve_dict:
            d = deepcopy(d)

        id = d.pop("id")
        geometry = d.pop("geometry")
        properties = d.pop("properties")
        bbox = d.pop("bbox", None)
        stac_extensions = d.get("stac_extensions")
        collection_id = d.pop("collection", None)

        datetime = properties.get("datetime")
        if datetime is not None:
            datetime = str_to_datetime(datetime)
        links = d.pop("links")
        assets = d.pop("assets")

        d.pop("type")
        d.pop("stac_version")

        item = cls(
            id=id,
            geometry=geometry,
            bbox=bbox,
            datetime=datetime,
            properties=properties,
            stac_extensions=stac_extensions,
            collection=collection_id,
            extra_fields=d,
            assets={k: Asset.from_dict(v)
                    for k, v in assets.items()},
        )

        has_self_link = False
        for link in links:
            has_self_link |= link["rel"] == pystac.RelType.SELF
            item.add_link(Link.from_dict(link))

        if not has_self_link and href is not None:
            item.add_link(Link.self_href(href))

        if root:
            item.set_root(root)

        return item
Exemplo n.º 7
0
    def test_identify(self) -> None:
        collection_cache = CollectionCache()
        for example in self.examples:
            with self.subTest(example.path):
                path = example.path
                d = pystac.StacIO.default().read_json(path)
                if identify_stac_object_type(d) == pystac.STACObjectType.ITEM:
                    merge_common_properties(
                        d, json_href=path, collection_cache=collection_cache
                    )

                actual = identify_stac_object(d)
                # Explicitly cover __repr__ functions in tests
                str_info = str(actual)
                self.assertIsInstance(str_info, str)

                msg = "Failed {}:".format(path)

                self.assertEqual(actual.object_type, example.object_type, msg=msg)
                version_contained_in_range = actual.version_range.contains(
                    example.stac_version
                )
                self.assertTrue(version_contained_in_range, msg=msg)
                self.assertEqual(
                    set(actual.extensions), set(example.extensions), msg=msg
                )
Exemplo n.º 8
0
    def test_identify(self):
        collection_cache = CollectionCache()
        for example in self.examples:
            path = example['path']
            d = STAC_IO.read_json(path)
            if identify_stac_object_type(d) == STACObjectType.ITEM:
                try:
                    merge_common_properties(d, json_href=path, collection_cache=collection_cache)
                except HTTPError:
                    pass

            actual = identify_stac_object(d)
            # Explicitly cover __repr__ functions in tests
            str_info = str(actual)
            self.assertIsInstance(str_info, str)

            msg = 'Failed {}:'.format(path)

            self.assertEqual(actual.object_type, example['object_type'], msg=msg)
            version_contained_in_range = actual.version_range.contains(example['stac_version'])
            self.assertTrue(version_contained_in_range, msg=msg)
            self.assertEqual(set(actual.common_extensions),
                             set(example['common_extensions']),
                             msg=msg)
            self.assertEqual(set(actual.custom_extensions),
                             set(example['custom_extensions']),
                             msg=msg)
Exemplo n.º 9
0
    def get_stac_type(self, stac_content: dict) -> str:
        """Identify the STAC object type

        :param stac_content: STAC content dictionary
        :type stac_content: dict
        :return: STAC object type
        :rtype: str
        """
        stac_object = identify_stac_object(stac_content)
        return stac_object.object_type.lower()
Exemplo n.º 10
0
    def get_stac_version(self, stac_content: dict) -> str:
        """Identify the STAC object type

        :param stac_content: STAC content dictionary
        :type stac_content: dict
        :return: STAC object type
        :rtype: str
        """
        stac_object = identify_stac_object(stac_content)
        return stac_object.version_range.max_version
Exemplo n.º 11
0
def get_stac_type(stac_content) -> str:
    try:
        content_types = ["Item", "Catalog", "Collection"]
        if "type" in stac_content and stac_content["type"] == "Feature":
            return "Item"
        if "type" in stac_content and stac_content["type"] in content_types:
            return stac_content["type"]
        stac_object = identify_stac_object(stac_content)
        return stac_object.object_type
    except TypeError as e:
        return str(e)
Exemplo n.º 12
0
    def from_dict(
        cls,
        d: Dict[str, Any],
        href: Optional[str] = None,
        root: Optional["Catalog"] = None,
        migrate: bool = False,
        preserve_dict: bool = True,
    ) -> "Catalog":
        if migrate:
            info = identify_stac_object(d)
            d = migrate_to_latest(d, info)

        if not cls.matches_object_type(d):
            raise STACTypeError(f"{d} does not represent a {cls.__name__} instance")

        catalog_type = CatalogType.determine_type(d)

        if preserve_dict:
            d = deepcopy(d)

        id = d.pop("id")
        description = d.pop("description")
        title = d.pop("title", None)
        stac_extensions = d.pop("stac_extensions", None)
        links = d.pop("links")

        d.pop("stac_version")

        cat = cls(
            id=id,
            description=description,
            title=title,
            stac_extensions=stac_extensions,
            extra_fields=d,
            href=href,
            catalog_type=catalog_type or CatalogType.ABSOLUTE_PUBLISHED,
        )

        for link in links:
            if link["rel"] == pystac.RelType.ROOT:
                # Remove the link that's generated in Catalog's constructor.
                cat.remove_links(pystac.RelType.ROOT)

            if link["rel"] != pystac.RelType.SELF or href is None:
                cat.add_link(Link.from_dict(link))

        if root:
            cat.set_root(root)

        return cat
Exemplo n.º 13
0
    def test_identify_invalid_stac_object_with_version(self) -> None:
        # Has stac_version but is not a valid STAC object
        invalid_dict = {
            "id": "concepts",
            "title": "Concepts catalogs",
            "links": [
                {
                    "rel": "self",
                    "type": "application/json",
                    "href": "https://tamn.snapplanet.io/catalogs/concepts",
                },
                {
                    "rel": "root",
                    "type": "application/json",
                    "href": "https://tamn.snapplanet.io",
                },
            ],
            "stac_version": "1.0.0",
        }

        with self.assertRaises(pystac.STACTypeError) as ctx:
            identify_stac_object(invalid_dict)

        self.assertIn("JSON does not represent a STAC object", str(ctx.exception))
Exemplo n.º 14
0
    def from_dict(
        cls,
        d: Dict[str, Any],
        href: Optional[str] = None,
        root: Optional[Catalog] = None,
        migrate: bool = False,
        preserve_dict: bool = True,
    ) -> "Collection":
        if migrate:
            info = identify_stac_object(d)
            d = migrate_to_latest(d, info)

        if not cls.matches_object_type(d):
            raise STACTypeError(
                f"{d} does not represent a {cls.__name__} instance")

        catalog_type = CatalogType.determine_type(d)

        if preserve_dict:
            d = deepcopy(d)

        id = d.pop("id")
        description = d.pop("description")
        license = d.pop("license")
        extent = Extent.from_dict(d.pop("extent"))
        title = d.get("title")
        stac_extensions = d.get("stac_extensions")
        keywords = d.get("keywords")
        providers = d.get("providers")
        if providers is not None:
            providers = list(
                map(lambda x: pystac.Provider.from_dict(x), providers))
        summaries = d.get("summaries")
        if summaries is not None:
            summaries = Summaries(summaries)

        assets: Optional[Dict[str, Any]] = {
            k: Asset.from_dict(v)
            for k, v in d.get("assets", {}).items()
        }
        links = d.pop("links")

        d.pop("stac_version")

        collection = cls(
            id=id,
            description=description,
            extent=extent,
            title=title,
            stac_extensions=stac_extensions,
            extra_fields=d,
            license=license,
            keywords=keywords,
            providers=providers,
            summaries=summaries,
            href=href,
            catalog_type=catalog_type,
            assets=assets,
        )

        for link in links:
            if link["rel"] == pystac.RelType.ROOT:
                # Remove the link that's generated in Catalog's constructor.
                collection.remove_links(pystac.RelType.ROOT)

            if link["rel"] != pystac.RelType.SELF or href is None:
                collection.add_link(Link.from_dict(link))

        if root:
            collection.set_root(root)

        return collection
Exemplo n.º 15
0
                            try:
                                js = json.loads(f.read())
                            except json.decoder.JSONDecodeError:
                                # Account for bad examples that can't be parsed.
                                js = {}
                            example_version = js.get('stac_version')
                        if example_version is not None and \
                           example_version > args.previous_version:
                            relpath = '{}/{}'.format(
                                STAC_VERSION,
                                path.replace('{}/'.format(tmp_dir), ''))
                            target_path = os.path.join(examples_dir, relpath)

                            print('Creating example at {}'.format(target_path))

                            info = identify_stac_object(js)

                            # Handle the case where there are collection links that
                            # don't exist.
                            if info.object_type == STACObjectType.ITEM:
                                js = remove_bad_collection(js)

                            d = os.path.dirname(target_path)
                            if not os.path.isdir(d):
                                os.makedirs(d)

                            with open(target_path, 'w') as f:
                                f.write(json.dumps(js, indent=4))

                            # Add info to the new example-info.csv lines
                            example_csv_lines.append([