diff --git a/docs/conf.py b/docs/conf.py index 13b847d75..39a01df9e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,6 +15,8 @@ import os import sys import subprocess +from typing import Any, Dict + sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('../')) from pystac.version import __version__ @@ -134,7 +136,7 @@ # -- Options for LaTeX output ------------------------------------------------ -latex_elements = { +latex_elements: Dict[str, Any] = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', diff --git a/mypy.ini b/mypy.ini index 132834a06..370f59b32 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,3 +1,4 @@ [mypy] +disallow_untyped_defs = True ignore_missing_imports = True -disallow_untyped_defs = True \ No newline at end of file +show_error_codes = True diff --git a/pystac/collection.py b/pystac/collection.py index 117754db8..cf0f38c40 100644 --- a/pystac/collection.py +++ b/pystac/collection.py @@ -431,9 +431,9 @@ def to_dict(self) -> Dict[str, Any]: return {"minimum": self.minimum, "maximum": self.maximum} @classmethod - def from_dict(cls, d: Dict[str, Any], typ: Type[T] = Any) -> "RangeSummary[T]": - minimum: Optional[T] = get_required(d.get("minimum"), "RangeSummary", "minimum") - maximum: Optional[T] = get_required(d.get("maximum"), "RangeSummary", "maximum") + def from_dict(cls, d: Dict[str, Any]) -> "RangeSummary[T]": + minimum: T = get_required(d.get("minimum"), "RangeSummary", "minimum") + maximum: T = get_required(d.get("maximum"), "RangeSummary", "maximum") return cls(minimum=minimum, maximum=maximum) @@ -483,7 +483,7 @@ def remove(self, prop_key: str) -> None: self.schemas.pop(prop_key, None) self.other.pop(prop_key, None) - def is_empty(self): + def is_empty(self) -> bool: return not ( any(self.lists) or any(self.ranges) or any(self.schemas) or any(self.other) ) diff --git a/pystac/extensions/base.py b/pystac/extensions/base.py index 191f4521e..6ed1d4a55 100644 --- a/pystac/extensions/base.py +++ b/pystac/extensions/base.py @@ -1,17 +1,19 @@ from abc import ABC, abstractmethod from typing import Generic, Iterable, List, Optional, Dict, Any, Type, TypeVar, Union -import pystac +from pystac import Collection, RangeSummary, STACObject, Summaries class SummariesExtension: - def __init__(self, collection: pystac.Collection) -> None: + summaries: Summaries + + def __init__(self, collection: Collection) -> None: self.summaries = collection.summaries def _set_summary( self, prop_key: str, - v: Optional[Union[List[Any], pystac.RangeSummary[Any], Dict[str, Any]]], + v: Optional[Union[List[Any], RangeSummary[Any], Dict[str, Any]]], ) -> None: if v is None: self.summaries.remove(prop_key) @@ -26,8 +28,8 @@ class PropertiesExtension(ABC): properties: Dict[str, Any] additional_read_properties: Optional[Iterable[Dict[str, Any]]] = None - def _get_property(self, prop_name: str, typ: Type[P] = Type[Any]) -> Optional[P]: - result: Optional[typ] = self.properties.get(prop_name) + def _get_property(self, prop_name: str, typ: Type[P]) -> Optional[P]: + result = self.properties.get(prop_name) if result is not None: return result if self.additional_read_properties is not None: @@ -46,7 +48,7 @@ def _set_property( self.properties[prop_name] = v -S = TypeVar("S", bound=pystac.STACObject) +S = TypeVar("S", bound=STACObject) class ExtensionManagementMixin(Generic[S], ABC): diff --git a/pystac/extensions/datacube.py b/pystac/extensions/datacube.py index 118366c9f..4dcc0d0a2 100644 --- a/pystac/extensions/datacube.py +++ b/pystac/extensions/datacube.py @@ -386,4 +386,4 @@ class DatacubeExtensionHooks(ExtensionHooks): ) -DATACUBE_EXTENSION_HOOKS = DatacubeExtensionHooks() +DATACUBE_EXTENSION_HOOKS: ExtensionHooks = DatacubeExtensionHooks() diff --git a/pystac/extensions/eo.py b/pystac/extensions/eo.py index 026635250..8fb835aef 100644 --- a/pystac/extensions/eo.py +++ b/pystac/extensions/eo.py @@ -272,18 +272,18 @@ def bands(self) -> Optional[List[Band]]: """ return self._get_bands() - def _get_bands(self) -> Optional[List[Band]]: - return map_opt( - lambda bands: [Band(b) for b in bands], - self._get_property(BANDS_PROP, List[Dict[str, Any]]), - ) - @bands.setter def bands(self, v: Optional[List[Band]]) -> None: self._set_property( BANDS_PROP, map_opt(lambda bands: [b.to_dict() for b in bands], v) ) + def _get_bands(self) -> Optional[List[Band]]: + return map_opt( + lambda bands: [Band(b) for b in bands], + self._get_property(BANDS_PROP, List[Dict[str, Any]]), + ) + @property def cloud_cover(self) -> Optional[float]: """Get or sets the estimate of cloud cover as a percentage (0-100) of the @@ -365,6 +365,7 @@ def bands(self) -> Optional[List[Band]]: """Get or sets a list of :class:`~pystac.Band` objects that represent the available bands. """ + return map_opt( lambda bands: [Band(b) for b in bands], self.summaries.get_list(BANDS_PROP, Dict[str, Any]), diff --git a/pystac/extensions/file.py b/pystac/extensions/file.py index 264ad5fdf..8f3027785 100644 --- a/pystac/extensions/file.py +++ b/pystac/extensions/file.py @@ -188,6 +188,7 @@ def data_type(self) -> Optional[List[FileDataType]]: Returns: FileDataType """ + return map_opt( lambda x: [FileDataType(t) for t in x], self.summaries.get_list(DATA_TYPE_PROP, str), @@ -261,4 +262,4 @@ def migrate( obj["assets"][key][CHECKSUM_PROP] = old_checksum[key] -FILE_EXTENSION_HOOKS = FileExtensionHooks() +FILE_EXTENSION_HOOKS: ExtensionHooks = FileExtensionHooks() diff --git a/pystac/extensions/hooks.py b/pystac/extensions/hooks.py index 33a7583d6..388e35a50 100644 --- a/pystac/extensions/hooks.py +++ b/pystac/extensions/hooks.py @@ -18,10 +18,10 @@ def schema_uri(self) -> str: @property @abstractmethod - def prev_extension_ids(self) -> List[str]: - """A list of previous extension IDs (schema URIs or old short ids) + def prev_extension_ids(self) -> Set[str]: + """A set of previous extension IDs (schema URIs or old short ids) that should be migrated to the latest schema URI in the 'stac_extensions' - property. Override with a class attribute so that the list of previous + property. Override with a class attribute so that the set of previous IDs is only created once. """ pass diff --git a/pystac/extensions/item_assets.py b/pystac/extensions/item_assets.py index a5f2b44be..5b362017d 100644 --- a/pystac/extensions/item_assets.py +++ b/pystac/extensions/item_assets.py @@ -27,7 +27,7 @@ def __init__(self, properties: Dict[str, Any]) -> None: @property def title(self) -> Optional[str]: - self.properties.get(ASSET_TITLE_PROP) + return self.properties.get(ASSET_TITLE_PROP) @title.setter def title(self, v: Optional[str]) -> None: @@ -38,7 +38,7 @@ def title(self, v: Optional[str]) -> None: @property def description(self) -> Optional[str]: - self.properties.get(ASSET_DESC_PROP) + return self.properties.get(ASSET_DESC_PROP) @description.setter def description(self, v: Optional[str]) -> None: @@ -49,7 +49,7 @@ def description(self, v: Optional[str]) -> None: @property def media_type(self) -> Optional[str]: - self.properties.get(ASSET_TYPE_PROP) + return self.properties.get(ASSET_TYPE_PROP) @media_type.setter def media_type(self, v: Optional[str]) -> None: @@ -60,7 +60,7 @@ def media_type(self, v: Optional[str]) -> None: @property def roles(self) -> Optional[List[str]]: - self.properties.get(ASSET_ROLES_PROP) + return self.properties.get(ASSET_ROLES_PROP) @roles.setter def roles(self, v: Optional[List[str]]) -> None: @@ -78,7 +78,7 @@ def create_asset(self, href: str) -> pystac.Asset: roles=self.roles, properties={ k: v - for k, v in self.properties + for k, v in self.properties.items() if k not in set( [ @@ -98,7 +98,7 @@ def __init__(self, collection: pystac.Collection) -> None: @property def item_assets(self) -> Dict[str, AssetDefinition]: - result = get_required( + result: Dict[str, Any] = get_required( self.collection.extra_fields.get(ITEM_ASSETS_PROP), self, ITEM_ASSETS_PROP ) return {k: AssetDefinition(v) for k, v in result.items()} @@ -141,4 +141,4 @@ def migrate( super().migrate(obj, version, info) -ITEM_ASSETS_EXTENSION_HOOKS = ItemAssetsExtensionHooks() +ITEM_ASSETS_EXTENSION_HOOKS: ExtensionHooks = ItemAssetsExtensionHooks() diff --git a/pystac/extensions/pointcloud.py b/pystac/extensions/pointcloud.py index fc922cd55..f8ec27e34 100644 --- a/pystac/extensions/pointcloud.py +++ b/pystac/extensions/pointcloud.py @@ -563,4 +563,4 @@ class PointcloudExtensionHooks(ExtensionHooks): stac_object_types: Set[pystac.STACObjectType] = set([pystac.STACObjectType.ITEM]) -POINTCLOUD_EXTENSION_HOOKS = PointcloudExtensionHooks() +POINTCLOUD_EXTENSION_HOOKS: ExtensionHooks = PointcloudExtensionHooks() diff --git a/pystac/extensions/projection.py b/pystac/extensions/projection.py index 2f58de818..ac525fe38 100644 --- a/pystac/extensions/projection.py +++ b/pystac/extensions/projection.py @@ -294,4 +294,4 @@ class ProjectionExtensionHooks(ExtensionHooks): stac_object_types: Set[pystac.STACObjectType] = set([pystac.STACObjectType.ITEM]) -PROJECTION_EXTENSION_HOOKS = ProjectionExtensionHooks() +PROJECTION_EXTENSION_HOOKS: ExtensionHooks = ProjectionExtensionHooks() diff --git a/pystac/extensions/sar.py b/pystac/extensions/sar.py index 8c1a5f5b1..089a567dc 100644 --- a/pystac/extensions/sar.py +++ b/pystac/extensions/sar.py @@ -8,8 +8,7 @@ import pystac from pystac.serialization.identify import STACJSONDescription, STACVersionID -from pystac.extensions.base import ExtensionManagementMixin -from pystac.extensions.projection import ProjectionExtension +from pystac.extensions.base import ExtensionManagementMixin, PropertiesExtension from pystac.extensions.hooks import ExtensionHooks from pystac.utils import get_required, map_opt @@ -59,7 +58,7 @@ class ObservationDirection(enum.Enum): class SarExtension( - Generic[T], ProjectionExtension[T], ExtensionManagementMixin[pystac.Item] + Generic[T], PropertiesExtension, ExtensionManagementMixin[pystac.Item] ): """SarItemExt extends Item to add sar properties to a STAC Item. diff --git a/pystac/extensions/sat.py b/pystac/extensions/sat.py index 4c61a3527..2f583fdfe 100644 --- a/pystac/extensions/sat.py +++ b/pystac/extensions/sat.py @@ -133,4 +133,4 @@ class SatExtensionHooks(ExtensionHooks): stac_object_types: Set[pystac.STACObjectType] = set([pystac.STACObjectType.ITEM]) -SAT_EXTENSION_HOOKS = SatExtensionHooks() +SAT_EXTENSION_HOOKS: ExtensionHooks = SatExtensionHooks() diff --git a/pystac/extensions/scientific.py b/pystac/extensions/scientific.py index 9174ef6a5..6e8d6aecc 100644 --- a/pystac/extensions/scientific.py +++ b/pystac/extensions/scientific.py @@ -233,4 +233,4 @@ class ScientificExtensionHooks(ExtensionHooks): ) -SCIENTIFIC_EXTENSION_HOOKS = ScientificExtensionHooks() +SCIENTIFIC_EXTENSION_HOOKS: ExtensionHooks = ScientificExtensionHooks() diff --git a/pystac/extensions/timestamps.py b/pystac/extensions/timestamps.py index 7516ff47d..211049900 100644 --- a/pystac/extensions/timestamps.py +++ b/pystac/extensions/timestamps.py @@ -154,4 +154,4 @@ class TimestampsExtensionHooks(ExtensionHooks): stac_object_types: Set[pystac.STACObjectType] = set([pystac.STACObjectType.ITEM]) -TIMESTAMPS_EXTENSION_HOOKS = TimestampsExtensionHooks() +TIMESTAMPS_EXTENSION_HOOKS: ExtensionHooks = TimestampsExtensionHooks() diff --git a/pystac/extensions/view.py b/pystac/extensions/view.py index 77c26b34d..4101b9f7a 100644 --- a/pystac/extensions/view.py +++ b/pystac/extensions/view.py @@ -195,4 +195,4 @@ class ViewExtensionHooks(ExtensionHooks): stac_object_types: Set[pystac.STACObjectType] = set([pystac.STACObjectType.ITEM]) -VIEW_EXTENSION_HOOKS = ViewExtensionHooks() +VIEW_EXTENSION_HOOKS: ExtensionHooks = ViewExtensionHooks() diff --git a/pystac/stac_io.py b/pystac/stac_io.py index d7e67cfa0..b5b8b0a1a 100644 --- a/pystac/stac_io.py +++ b/pystac/stac_io.py @@ -25,7 +25,7 @@ try: import orjson # type: ignore except ImportError: - orjson = None + orjson = None # type: ignore[assignment] if TYPE_CHECKING: from pystac.stac_object import STACObject as STACObject_Type @@ -170,6 +170,7 @@ class DefaultStacIO(StacIO): def read_text( self, source: Union[str, "Link_Type"], *args: Any, **kwargs: Any ) -> str: + href: Optional[str] if isinstance(source, str): href = source else: @@ -193,6 +194,7 @@ def read_text_from_href(self, href: str, *args: Any, **kwargs: Any) -> str: def write_text( self, dest: Union[str, "Link_Type"], txt: str, *args: Any, **kwargs: Any ) -> None: + href: Optional[str] if isinstance(dest, str): href = dest else: diff --git a/requirements-dev.txt b/requirements-dev.txt index 9a996c384..ac2b12bae 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,4 @@ -mypy==0.790 +mypy==0.812 flake8==3.8.* black==21.4b2 diff --git a/scripts/test b/scripts/test index 2cfc070b3..ea6b4f8f1 100755 --- a/scripts/test +++ b/scripts/test @@ -17,6 +17,12 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then if [ "${1:-}" = "--help" ]; then usage else + echo + echo " -- CHECKING TYPES WITH MYPY --" + echo + + mypy docs pystac setup.py tests + echo echo " -- CHECKING TYPES WITH PYRIGHT --" echo diff --git a/setup.py b/setup.py index 6851f848a..7993d8eb1 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages from glob import glob -__version__ = load_source('pystac.version', 'pystac/version.py').__version__ +__version__ = load_source('pystac.version', 'pystac/version.py').__version__ # type: ignore from os.path import ( basename, diff --git a/tests/extensions/test_custom.py b/tests/extensions/test_custom.py index f3939b040..76fc5444f 100644 --- a/tests/extensions/test_custom.py +++ b/tests/extensions/test_custom.py @@ -34,7 +34,7 @@ def apply(self, test_prop: Optional[str]) -> None: @property def test_prop(self) -> Optional[str]: - self._get_property(TEST_PROP, str) + return self._get_property(TEST_PROP, str) @test_prop.setter def test_prop(self, v: Optional[str]) -> None: @@ -139,7 +139,7 @@ def migrate( class CustomExtensionTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: pystac.EXTENSION_HOOKS.add_extension_hooks(CustomExtensionHooks()) def tearDown(self) -> None: @@ -147,5 +147,5 @@ def tearDown(self) -> None: # TODO: Test custom extensions and extension hooks - def test_migrates(self): + def test_migrates(self) -> None: pass diff --git a/tests/extensions/test_eo.py b/tests/extensions/test_eo.py index 0fe73ab10..5afbb6903 100644 --- a/tests/extensions/test_eo.py +++ b/tests/extensions/test_eo.py @@ -16,21 +16,21 @@ class EOTest(unittest.TestCase): ) EO_COLLECTION_URI = TestCases.get_path("data-files/eo/eo-collection.json") - def setUp(self): + def setUp(self) -> None: self.maxDiff = None - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: with open(self.LANDSAT_EXAMPLE_URI) as f: item_dict = json.load(f) test_to_from_dict(self, Item, item_dict) - def test_validate_eo(self): + def test_validate_eo(self) -> None: item = pystac.read_file(self.LANDSAT_EXAMPLE_URI) item2 = pystac.read_file(self.BANDS_IN_ITEM_URI) item.validate() item2.validate() - def test_bands(self): + def test_bands(self) -> None: item = pystac.Item.from_file(self.BANDS_IN_ITEM_URI) # Get @@ -56,7 +56,7 @@ def test_bands(self): self.assertEqual(len(EOExtension.ext(item).bands or []), 3) item.validate() - def test_asset_bands(self): + def test_asset_bands(self) -> None: item = pystac.Item.from_file(self.LANDSAT_EXAMPLE_URI) # Get @@ -98,7 +98,7 @@ def test_asset_bands(self): self.assertEqual(len(item.assets["test"].properties["eo:bands"]), 3) - def test_cloud_cover(self): + def test_cloud_cover(self) -> None: item = pystac.Item.from_file(self.LANDSAT_EXAMPLE_URI) # Get @@ -125,13 +125,14 @@ def test_cloud_cover(self): item.validate() - def test_summaries(self): + def test_summaries(self) -> None: col = pystac.Collection.from_file(self.EO_COLLECTION_URI) eo_summaries = EOExtension.summaries(col) # Get cloud_cover_summaries = eo_summaries.cloud_cover + assert cloud_cover_summaries is not None self.assertEqual(cloud_cover_summaries.minimum, 0.0) self.assertEqual(cloud_cover_summaries.maximum, 80.0) @@ -148,7 +149,7 @@ def test_summaries(self): self.assertEqual(len(col_dict["summaries"]["eo:bands"]), 1) self.assertEqual(col_dict["summaries"]["eo:cloud_cover"]["minimum"], 1.0) - def test_read_pre_09_fields_into_common_metadata(self): + def test_read_pre_09_fields_into_common_metadata(self) -> None: eo_item = pystac.Item.from_file( TestCases.get_path( "data-files/examples/0.8.1/item-spec/examples/" "landsat8-sample.json" @@ -158,7 +159,7 @@ def test_read_pre_09_fields_into_common_metadata(self): self.assertEqual(eo_item.common_metadata.platform, "landsat-8") self.assertEqual(eo_item.common_metadata.instruments, ["oli_tirs"]) - def test_reads_asset_bands_in_pre_1_0_version(self): + def test_reads_asset_bands_in_pre_1_0_version(self) -> None: item = pystac.Item.from_file( TestCases.get_path( "data-files/examples/0.9.0/item-spec/examples/" "landsat8-sample.json" @@ -170,7 +171,7 @@ def test_reads_asset_bands_in_pre_1_0_version(self): self.assertEqual(len(bands or []), 1) self.assertEqual(get_opt(bands)[0].common_name, "cirrus") - def test_reads_gsd_in_pre_1_0_version(self): + def test_reads_gsd_in_pre_1_0_version(self) -> None: eo_item = pystac.Item.from_file( TestCases.get_path( "data-files/examples/0.9.0/item-spec/examples/" "landsat8-sample.json" diff --git a/tests/extensions/test_file.py b/tests/extensions/test_file.py index b0952ecf0..ff41e087e 100644 --- a/tests/extensions/test_file.py +++ b/tests/extensions/test_file.py @@ -9,19 +9,19 @@ class FileTest(unittest.TestCase): FILE_EXAMPLE_URI = TestCases.get_path("data-files/file/file-example.json") - def setUp(self): + def setUp(self) -> None: self.maxDiff = None - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: with open(self.FILE_EXAMPLE_URI) as f: item_dict = json.load(f) test_to_from_dict(self, pystac.Item, item_dict) - def test_validate_file(self): + def test_validate_file(self) -> None: item = pystac.Item.from_file(self.FILE_EXAMPLE_URI) item.validate() - def test_asset_size(self): + def test_asset_size(self) -> None: item = pystac.Item.from_file(self.FILE_EXAMPLE_URI) asset = item.assets["thumbnail"] @@ -34,7 +34,7 @@ def test_asset_size(self): self.assertEqual(new_size, FileExtension.ext(asset).size) item.validate() - def test_asset_checksum(self): + def test_asset_checksum(self) -> None: item = pystac.Item.from_file(self.FILE_EXAMPLE_URI) asset = item.assets["thumbnail"] @@ -50,7 +50,7 @@ def test_asset_checksum(self): self.assertEqual(new_checksum, FileExtension.ext(asset).checksum) item.validate() - def test_asset_data_type(self): + def test_asset_data_type(self) -> None: item = pystac.Item.from_file(self.FILE_EXAMPLE_URI) asset = item.assets["thumbnail"] @@ -63,7 +63,7 @@ def test_asset_data_type(self): self.assertEqual(new_data_type, FileExtension.ext(asset).data_type) item.validate() - def test_asset_nodata(self): + def test_asset_nodata(self) -> None: item = pystac.Item.from_file(self.FILE_EXAMPLE_URI) asset = item.assets["thumbnail"] @@ -76,7 +76,7 @@ def test_asset_nodata(self): self.assertEqual(new_nodata, FileExtension.ext(asset).nodata) item.validate() - def test_migrates_old_checksum(self): + def test_migrates_old_checksum(self) -> None: example_path = TestCases.get_path( "data-files/examples/1.0.0-beta.2/" "extensions/checksum/examples/sentinel1.json" diff --git a/tests/extensions/test_label.py b/tests/extensions/test_label.py index d6c08920d..a581507c8 100644 --- a/tests/extensions/test_label.py +++ b/tests/extensions/test_label.py @@ -19,7 +19,7 @@ class LabelTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.maxDiff = None self.label_example_1_uri = TestCases.get_path( "data-files/label/label-example-1.json" @@ -28,13 +28,13 @@ def setUp(self): "data-files/label/label-example-2.json" ) - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: with open(self.label_example_1_uri) as f: label_example_1_dict = json.load(f) test_to_from_dict(self, Item, label_example_1_dict) - def test_from_file(self): + def test_from_file(self) -> None: label_example_1 = Item.from_file(self.label_example_1_uri) overviews = get_opt(LabelExtension.ext(label_example_1).label_overviews) @@ -47,7 +47,7 @@ def test_from_file(self): label_example_2.validate() - def test_from_file_pre_081(self): + def test_from_file_pre_081(self) -> None: d = pystac.StacIO.default().read_json(self.label_example_1_uri) d["stac_version"] = "0.8.0-rc1" @@ -63,7 +63,7 @@ def test_from_file_pre_081(self): self.assertEqual(len(LabelExtension.ext(label_example_1).label_tasks or []), 2) - def test_get_sources(self): + def test_get_sources(self) -> None: cat = TestCases.test_case_1() items = cat.get_all_items() @@ -75,7 +75,7 @@ def test_get_sources(self): self.assertEqual(len(sources), 1) self.assertTrue(sources[0].id in item_ids) - def test_validate_label(self): + def test_validate_label(self) -> None: with open(self.label_example_1_uri) as f: label_example_1_dict = json.load(f) pystac.validation.validate_dict( @@ -89,9 +89,10 @@ def test_validate_label(self): cat_read = Catalog.from_file(os.path.join(cat_dir, "catalog.json")) label_item_read = cat_read.get_item("area-2-2-labels", recursive=True) + assert label_item_read is not None label_item_read.validate() - def test_read_label_item_owns_asset(self): + def test_read_label_item_owns_asset(self) -> None: item = next( x for x in TestCases.test_case_2().get_all_items() @@ -101,7 +102,7 @@ def test_read_label_item_owns_asset(self): for asset_key in item.assets: self.assertEqual(item.assets[asset_key].owner, item) - def test_label_description(self): + def test_label_description(self) -> None: label_item = pystac.Item.from_file(self.label_example_1_uri) # Get @@ -116,7 +117,7 @@ def test_label_description(self): ) label_item.validate() - def test_label_type(self): + def test_label_type(self) -> None: label_item = pystac.Item.from_file(self.label_example_1_uri) # Get @@ -129,7 +130,7 @@ def test_label_type(self): self.assertEqual(LabelType.RASTER, label_item.properties["label:type"]) label_item.validate() - def test_label_properties(self): + def test_label_properties(self) -> None: label_item = pystac.Item.from_file(self.label_example_1_uri) label_item2 = pystac.Item.from_file(self.label_example_2_uri) @@ -145,7 +146,7 @@ def test_label_properties(self): self.assertEqual(["prop1", "prop2"], label_item.properties["label:properties"]) label_item.validate() - def test_label_classes(self): + def test_label_classes(self) -> None: # Get label_item = pystac.Item.from_file(self.label_example_1_uri) label_classes = LabelExtension.ext(label_item).label_classes @@ -171,7 +172,7 @@ def test_label_classes(self): label_item.validate() - def test_label_tasks(self): + def test_label_tasks(self) -> None: label_item = pystac.Item.from_file(self.label_example_1_uri) # Get @@ -184,7 +185,7 @@ def test_label_tasks(self): self.assertEqual(["classification"], label_item.properties["label:tasks"]) label_item.validate() - def test_label_methods(self): + def test_label_methods(self) -> None: label_item = pystac.Item.from_file(self.label_example_1_uri) # Get @@ -199,7 +200,7 @@ def test_label_methods(self): ) label_item.validate() - def test_label_overviews(self): + def test_label_overviews(self) -> None: # Get label_item = pystac.Item.from_file(self.label_example_1_uri) label_ext = LabelExtension.ext(label_item) @@ -215,14 +216,18 @@ def test_label_overviews(self): label_counts = get_opt(label_overviews[0].counts) self.assertEqual(label_counts[1].count, 17) - get_opt(label_ext.label_overviews)[0].counts[1].count = 18 + fisrt_overview_counts = get_opt(label_ext.label_overviews)[0].counts + assert fisrt_overview_counts is not None + fisrt_overview_counts[1].count = 18 self.assertEqual( label_item.properties["label:overviews"][0]["counts"][1]["count"], 18 ) label_statistics = get_opt(label_overviews[1].statistics) self.assertEqual(label_statistics[0].name, "mean") - get_opt(label_ext.label_overviews)[1].statistics[0].name = "avg" + second_overview_statistics = get_opt(label_ext.label_overviews)[1].statistics + assert second_overview_statistics is not None + second_overview_statistics[0].name = "avg" self.assertEqual( label_item.properties["label:overviews"][1]["statistics"][0]["name"], "avg" ) diff --git a/tests/extensions/test_pointcloud.py b/tests/extensions/test_pointcloud.py index c43d3e32b..e0f7370c0 100644 --- a/tests/extensions/test_pointcloud.py +++ b/tests/extensions/test_pointcloud.py @@ -17,19 +17,19 @@ class PointcloudTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.maxDiff = None self.example_uri = TestCases.get_path("data-files/pointcloud/example-laz.json") self.example_uri_no_statistics = TestCases.get_path( "data-files/pointcloud/example-laz-no-statistics.json" ) - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: with open(self.example_uri) as f: d = json.load(f) test_to_from_dict(self, pystac.Item, d) - def test_apply(self): + def test_apply(self) -> None: item = next(iter(TestCases.test_case_2().get_all_items())) self.assertFalse(PointcloudExtension.has_extension(item)) @@ -43,11 +43,11 @@ def test_apply(self): ) self.assertTrue(PointcloudExtension.has_extension(item)) - def test_validate_pointcloud(self): + def test_validate_pointcloud(self) -> None: item = pystac.read_file(self.example_uri) item.validate() - def test_count(self): + def test_count(self) -> None: pc_item = pystac.Item.from_file(self.example_uri) # Get @@ -69,7 +69,7 @@ def test_count(self): PointcloudExtension.ext(pc_item).count = "not_an_int" # type:ignore pc_item.validate() - def test_type(self): + def test_type(self) -> None: pc_item = pystac.Item.from_file(self.example_uri) # Get @@ -84,7 +84,7 @@ def test_type(self): # Validate pc_item.validate() - def test_encoding(self): + def test_encoding(self) -> None: pc_item = pystac.Item.from_file(self.example_uri) # Get @@ -99,7 +99,7 @@ def test_encoding(self): # Validate pc_item.validate() - def test_schemas(self): + def test_schemas(self) -> None: pc_item = pystac.Item.from_file(self.example_uri) # Get @@ -117,14 +117,14 @@ def test_schemas(self): # Validate pc_item.validate() - def test_statistics(self): + def test_statistics(self) -> None: pc_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("pc:statistics", pc_item.properties) - pc_statistics = [ - s.to_dict() for s in PointcloudExtension.ext(pc_item).statistics - ] + statistics = PointcloudExtension.ext(pc_item).statistics + assert statistics is not None + pc_statistics = [s.to_dict() for s in statistics] self.assertEqual(pc_statistics, pc_item.properties["pc:statistics"]) # Set @@ -150,7 +150,7 @@ def test_statistics(self): # Validate pc_item.validate - def test_density(self): + def test_density(self) -> None: pc_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("pc:density", pc_item.properties) @@ -163,7 +163,7 @@ def test_density(self): # Validate pc_item.validate() - def test_pointcloud_schema(self): + def test_pointcloud_schema(self) -> None: props: Dict[str, Any] = { "name": "test", "size": 8, @@ -197,7 +197,7 @@ def test_pointcloud_schema(self): with self.assertRaises(STACError): empty_schema.type - def test_pointcloud_statistics(self): + def test_pointcloud_statistics(self) -> None: props: Dict[str, Any] = { "average": 1, "count": 1, @@ -251,11 +251,11 @@ def test_pointcloud_statistics(self): with self.assertRaises(STACError): empty_stat.name - def test_statistics_accessor_when_no_stats(self): + def test_statistics_accessor_when_no_stats(self) -> None: pc_item = pystac.Item.from_file(self.example_uri_no_statistics) self.assertEqual(PointcloudExtension.ext(pc_item).statistics, None) - def test_asset_extension(self): + def test_asset_extension(self) -> None: asset = Asset( "https://github.com/PDAL/PDAL/blob" "/a6c986f68458e92414a66c664408bee4737bbb08/test/data/laz" @@ -273,7 +273,7 @@ def test_asset_extension(self): self.assertEqual(ext.properties, asset.properties) self.assertEqual(ext.additional_read_properties, [pc_item.properties]) - def test_ext(self): + def test_ext(self) -> None: pc_item = pystac.Item.from_file(self.example_uri_no_statistics) PointcloudExtension.ext(pc_item) asset = Asset( diff --git a/tests/extensions/test_projection.py b/tests/extensions/test_projection.py index 77be9f3ae..20ad81d7a 100644 --- a/tests/extensions/test_projection.py +++ b/tests/extensions/test_projection.py @@ -71,18 +71,18 @@ class ProjectionTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.maxDiff = None self.example_uri = TestCases.get_path( "data-files/projection/example-landsat8.json" ) - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: with open(self.example_uri) as f: d = json.load(f) test_to_from_dict(self, pystac.Item, d) - def test_apply(self): + def test_apply(self) -> None: item = next(iter(TestCases.test_case_2().get_all_items())) self.assertFalse(ProjectionExtension.has_extension(item)) @@ -98,7 +98,7 @@ def test_apply(self): transform=[30.0, 0.0, 224985.0, 0.0, -30.0, 6790215.0, 0.0, 0.0, 1.0], ) - def test_partial_apply(self): + def test_partial_apply(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) ProjectionExtension.ext(proj_item).apply(epsg=1111) @@ -106,11 +106,11 @@ def test_partial_apply(self): self.assertEqual(ProjectionExtension.ext(proj_item).epsg, 1111) proj_item.validate() - def test_validate_proj(self): + def test_validate_proj(self) -> None: item = pystac.Item.from_file(self.example_uri) item.validate() - def test_epsg(self): + def test_epsg(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get @@ -119,6 +119,7 @@ def test_epsg(self): self.assertEqual(proj_epsg, proj_item.properties["proj:epsg"]) # Set + assert proj_epsg is not None ProjectionExtension.ext(proj_item).epsg = proj_epsg + 100 self.assertEqual(proj_epsg + 100, proj_item.properties["proj:epsg"]) @@ -142,7 +143,7 @@ def test_epsg(self): # Validate proj_item.validate() - def test_wkt2(self): + def test_wkt2(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get @@ -177,7 +178,7 @@ def test_wkt2(self): # Validate proj_item.validate() - def test_projjson(self): + def test_projjson(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get @@ -196,9 +197,9 @@ def test_projjson(self): ProjectionExtension.ext(asset_no_prop).projjson, ProjectionExtension.ext(proj_item).projjson, ) - self.assertEqual( - ProjectionExtension.ext(asset_prop).projjson["id"]["code"], 9999 - ) + asset_prop_json = ProjectionExtension.ext(asset_prop).projjson + assert asset_prop_json is not None + self.assertEqual(asset_prop_json["id"]["code"], 9999) # Set to Asset asset_value = deepcopy(PROJJSON) @@ -208,9 +209,9 @@ def test_projjson(self): ProjectionExtension.ext(asset_no_prop).projjson, ProjectionExtension.ext(proj_item).projjson, ) - self.assertEqual( - ProjectionExtension.ext(asset_no_prop).projjson["id"]["code"], 7777 - ) + asset_no_prop_json = ProjectionExtension.ext(asset_no_prop).projjson + assert asset_no_prop_json is not None + self.assertEqual(asset_no_prop_json["id"]["code"], 7777) # Validate proj_item.validate() @@ -220,7 +221,7 @@ def test_projjson(self): ProjectionExtension.ext(proj_item).projjson = {"bad": "data"} proj_item.validate() - def test_geometry(self): + def test_geometry(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get @@ -239,10 +240,9 @@ def test_geometry(self): ProjectionExtension.ext(asset_no_prop).geometry, ProjectionExtension.ext(proj_item).geometry, ) - self.assertEqual( - ProjectionExtension.ext(asset_prop).geometry["coordinates"][0][0], - [0.0, 0.0], - ) + asset_prop_geometry = ProjectionExtension.ext(asset_prop).geometry + assert asset_prop_geometry is not None + self.assertEqual(asset_prop_geometry["coordinates"][0][0], [0.0, 0.0]) # Set to Asset asset_value: Dict[str, Any] = {"type": "Point", "coordinates": [1.0, 2.0]} @@ -261,7 +261,7 @@ def test_geometry(self): ProjectionExtension.ext(proj_item).geometry = {"bad": "data"} proj_item.validate() - def test_bbox(self): + def test_bbox(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get @@ -294,7 +294,7 @@ def test_bbox(self): # Validate proj_item.validate() - def test_centroid(self): + def test_centroid(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get @@ -335,7 +335,7 @@ def test_centroid(self): ProjectionExtension.ext(proj_item).centroid = {"lat": 2.0, "lng": 3.0} proj_item.validate() - def test_shape(self): + def test_shape(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get @@ -369,7 +369,7 @@ def test_shape(self): # Validate proj_item.validate() - def test_transform(self): + def test_transform(self) -> None: proj_item = pystac.Item.from_file(self.example_uri) # Get diff --git a/tests/extensions/test_sar.py b/tests/extensions/test_sar.py index ae3920b6b..2696eba39 100644 --- a/tests/extensions/test_sar.py +++ b/tests/extensions/test_sar.py @@ -21,14 +21,14 @@ def make_item() -> pystac.Item: class SarItemExtTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.item = make_item() - def test_stac_extensions(self): + def test_stac_extensions(self) -> None: self.assertTrue(SarExtension.has_extension(self.item)) - def test_required(self): + def test_required(self) -> None: mode: str = "Nonesense mode" frequency_band: sar.FrequencyBand = sar.FrequencyBand.P polarizations: List[sar.Polarization] = [ @@ -54,7 +54,7 @@ def test_required(self): self.item.validate() - def test_all(self): + def test_all(self) -> None: mode: str = "WV" frequency_band: sar.FrequencyBand = sar.FrequencyBand.KA polarizations: List[sar.Polarization] = [ @@ -127,7 +127,7 @@ def test_all(self): self.item.validate() - def test_polarization_must_be_list(self): + def test_polarization_must_be_list(self) -> None: mode: str = "Nonesense mode" frequency_band: sar.FrequencyBand = sar.FrequencyBand.P # Skip type hint as we are passing in an incorrect polarization. diff --git a/tests/extensions/test_sat.py b/tests/extensions/test_sat.py index 6831f2a7a..50fdbda5a 100644 --- a/tests/extensions/test_sat.py +++ b/tests/extensions/test_sat.py @@ -22,19 +22,19 @@ def make_item() -> pystac.Item: class SatTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.item = make_item() - def test_stac_extensions(self): + def test_stac_extensions(self) -> None: self.assertTrue(SatExtension.has_extension(self.item)) - def test_no_args_fails(self): + def test_no_args_fails(self) -> None: SatExtension.ext(self.item).apply() with self.assertRaises(pystac.STACValidationError): self.item.validate() - def test_orbit_state(self): + def test_orbit_state(self) -> None: orbit_state = sat.OrbitState.ASCENDING SatExtension.ext(self.item).apply(orbit_state) self.assertEqual(orbit_state, SatExtension.ext(self.item).orbit_state) @@ -42,7 +42,7 @@ def test_orbit_state(self): self.assertFalse(SatExtension.ext(self.item).relative_orbit) self.item.validate() - def test_relative_orbit(self): + def test_relative_orbit(self) -> None: relative_orbit = 1234 SatExtension.ext(self.item).apply(None, relative_orbit) self.assertEqual(relative_orbit, SatExtension.ext(self.item).relative_orbit) @@ -50,13 +50,13 @@ def test_relative_orbit(self): self.assertFalse(SatExtension.ext(self.item).orbit_state) self.item.validate() - def test_relative_orbit_no_negative(self): + def test_relative_orbit_no_negative(self) -> None: negative_relative_orbit = -2 SatExtension.ext(self.item).apply(None, negative_relative_orbit) with self.assertRaises(pystac.STACValidationError): self.item.validate() - def test_both(self): + def test_both(self) -> None: orbit_state = sat.OrbitState.DESCENDING relative_orbit = 4321 SatExtension.ext(self.item).apply(orbit_state, relative_orbit) @@ -64,7 +64,7 @@ def test_both(self): self.assertEqual(relative_orbit, SatExtension.ext(self.item).relative_orbit) self.item.validate() - def test_modify(self): + def test_modify(self) -> None: SatExtension.ext(self.item).apply(sat.OrbitState.DESCENDING, 999) orbit_state = sat.OrbitState.GEOSTATIONARY @@ -75,7 +75,7 @@ def test_modify(self): self.assertEqual(relative_orbit, SatExtension.ext(self.item).relative_orbit) self.item.validate() - def test_from_dict(self): + def test_from_dict(self) -> None: orbit_state = sat.OrbitState.GEOSTATIONARY relative_orbit = 1001 d: Dict[str, Any] = { @@ -96,7 +96,7 @@ def test_from_dict(self): self.assertEqual(orbit_state, SatExtension.ext(item).orbit_state) self.assertEqual(relative_orbit, SatExtension.ext(item).relative_orbit) - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: orbit_state = sat.OrbitState.GEOSTATIONARY relative_orbit = 1002 SatExtension.ext(self.item).apply(orbit_state, relative_orbit) @@ -108,14 +108,14 @@ def test_to_from_dict(self): self.assertEqual(orbit_state, SatExtension.ext(item).orbit_state) self.assertEqual(relative_orbit, SatExtension.ext(item).relative_orbit) - def test_clear_orbit_state(self): + def test_clear_orbit_state(self) -> None: SatExtension.ext(self.item).apply(sat.OrbitState.DESCENDING, 999) SatExtension.ext(self.item).orbit_state = None self.assertIsNone(SatExtension.ext(self.item).orbit_state) self.item.validate() - def test_clear_relative_orbit(self): + def test_clear_relative_orbit(self) -> None: SatExtension.ext(self.item).apply(sat.OrbitState.DESCENDING, 999) SatExtension.ext(self.item).relative_orbit = None diff --git a/tests/extensions/test_scientific.py b/tests/extensions/test_scientific.py index e0dc57cc9..eb1052351 100644 --- a/tests/extensions/test_scientific.py +++ b/tests/extensions/test_scientific.py @@ -2,6 +2,7 @@ import datetime import unittest +from typing import List, Optional import pystac from pystac.extensions import scientific @@ -40,14 +41,14 @@ def make_item() -> pystac.Item: class ItemScientificExtensionTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.item = make_item() - def test_stac_extensions(self): + def test_stac_extensions(self) -> None: self.assertTrue(ScientificExtension.has_extension(self.item)) - def test_doi(self): + def test_doi(self) -> None: ScientificExtension.ext(self.item).apply(DOI) self.assertEqual(DOI, ScientificExtension.ext(self.item).doi) self.assertIn(scientific.DOI, self.item.properties) @@ -69,14 +70,14 @@ def test_doi(self): self.assertEqual(PUB1_DOI_URL, link.get_href()) self.item.validate() - def test_citation(self): + def test_citation(self) -> None: ScientificExtension.ext(self.item).apply(citation=CITATION) self.assertEqual(CITATION, ScientificExtension.ext(self.item).citation) self.assertIn(scientific.CITATION, self.item.properties) self.assertFalse(self.item.get_links(scientific.CITE_AS)) self.item.validate() - def test_publications_one(self): + def test_publications_one(self) -> None: publications = PUBLICATIONS[:1] ScientificExtension.ext(self.item).apply(publications=publications) self.assertEqual([1], [int("1")]) @@ -89,7 +90,7 @@ def test_publications_one(self): self.assertCountEqual(expected, doi_urls) self.item.validate() - def test_publications(self): + def test_publications(self) -> None: ScientificExtension.ext(self.item).apply(publications=PUBLICATIONS) self.assertEqual(PUBLICATIONS, ScientificExtension.ext(self.item).publications) self.assertIn(scientific.PUBLICATIONS, self.item.properties) @@ -100,7 +101,7 @@ def test_publications(self): self.assertCountEqual(expected, doi_urls) self.item.validate() - def test_remove_publication_one(self): + def test_remove_publication_one(self) -> None: publications = PUBLICATIONS[:1] ScientificExtension.ext(self.item).apply(DOI, publications=publications) ScientificExtension.ext(self.item).remove_publication(publications[0]) @@ -110,7 +111,7 @@ def test_remove_publication_one(self): self.assertEqual(DOI_URL, links[0].target) self.item.validate() - def test_remove_all_publications_one(self): + def test_remove_all_publications_one(self) -> None: publications = PUBLICATIONS[:1] ScientificExtension.ext(self.item).apply(DOI, publications=publications) ScientificExtension.ext(self.item).remove_publication() @@ -120,7 +121,7 @@ def test_remove_all_publications_one(self): self.assertEqual(DOI_URL, links[0].target) self.item.validate() - def test_remove_publication_forward(self): + def test_remove_publication_forward(self) -> None: ScientificExtension.ext(self.item).apply(DOI, publications=PUBLICATIONS) ScientificExtension.ext(self.item).remove_publication(PUBLICATIONS[0]) @@ -140,7 +141,7 @@ def test_remove_publication_forward(self): self.assertEqual(DOI_URL, links[0].target) self.item.validate() - def test_remove_publication_reverse(self): + def test_remove_publication_reverse(self) -> None: ScientificExtension.ext(self.item).apply(DOI, publications=PUBLICATIONS) ScientificExtension.ext(self.item).remove_publication(PUBLICATIONS[1]) @@ -158,7 +159,7 @@ def test_remove_publication_reverse(self): self.assertEqual(DOI_URL, links[0].target) self.item.validate() - def test_remove_all_publications_with_some(self): + def test_remove_all_publications_with_some(self) -> None: ScientificExtension.ext(self.item).apply(DOI, publications=PUBLICATIONS) ScientificExtension.ext(self.item).remove_publication() self.assertFalse(ScientificExtension.ext(self.item).publications) @@ -167,7 +168,7 @@ def test_remove_all_publications_with_some(self): self.assertEqual(DOI_URL, links[0].target) self.item.validate() - def test_remove_all_publications_with_none(self): + def test_remove_all_publications_with_none(self) -> None: ScientificExtension.ext(self.item).apply(DOI) ScientificExtension.ext(self.item).remove_publication() self.assertFalse(ScientificExtension.ext(self.item).publications) @@ -183,7 +184,8 @@ def make_collection() -> pystac.Collection: end = start + datetime.timedelta(5, 4, 3, 2, 1) bboxes = [[-180.0, -90.0, 180.0, 90.0]] spatial_extent = pystac.SpatialExtent(bboxes) - temporal_extent = pystac.TemporalExtent([[start, end]]) + intervals: List[List[Optional[datetime.datetime]]] = [[start, end]] + temporal_extent = pystac.TemporalExtent(intervals) extent = pystac.Extent(spatial_extent, temporal_extent) collection = pystac.Collection(asset_id, "desc", extent) collection.set_self_href(URL_TEMPLATE % 2019) @@ -193,14 +195,14 @@ def make_collection() -> pystac.Collection: class CollectionScientificExtensionTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.collection = make_collection() - def test_stac_extensions(self): + def test_stac_extensions(self) -> None: self.assertTrue(ScientificExtension.has_extension(self.collection)) - def test_doi(self): + def test_doi(self) -> None: ScientificExtension.ext(self.collection).apply(DOI) self.assertEqual(DOI, ScientificExtension.ext(self.collection).doi) self.assertIn(scientific.DOI, self.collection.extra_fields) @@ -222,14 +224,14 @@ def test_doi(self): self.assertEqual(PUB1_DOI_URL, link.get_href()) self.collection.validate() - def test_citation(self): + def test_citation(self) -> None: ScientificExtension.ext(self.collection).apply(citation=CITATION) self.assertEqual(CITATION, ScientificExtension.ext(self.collection).citation) self.assertIn(scientific.CITATION, self.collection.extra_fields) self.assertFalse(self.collection.get_links(scientific.CITE_AS)) self.collection.validate() - def test_publications_one(self): + def test_publications_one(self) -> None: publications = PUBLICATIONS[:1] ScientificExtension.ext(self.collection).apply(publications=publications) self.assertEqual( @@ -244,7 +246,7 @@ def test_publications_one(self): self.collection.validate() - def test_publications(self): + def test_publications(self) -> None: ScientificExtension.ext(self.collection).apply(publications=PUBLICATIONS) self.assertEqual( PUBLICATIONS, ScientificExtension.ext(self.collection).publications @@ -258,7 +260,7 @@ def test_publications(self): self.collection.validate() - def test_remove_publication_one(self): + def test_remove_publication_one(self) -> None: publications = PUBLICATIONS[:1] ScientificExtension.ext(self.collection).apply(DOI, publications=publications) ScientificExtension.ext(self.collection).remove_publication(publications[0]) @@ -268,7 +270,7 @@ def test_remove_publication_one(self): self.assertEqual(DOI_URL, links[0].target) self.collection.validate() - def test_remove_all_publications_one(self): + def test_remove_all_publications_one(self) -> None: publications = PUBLICATIONS[:1] ScientificExtension.ext(self.collection).apply(DOI, publications=publications) ScientificExtension.ext(self.collection).remove_publication() @@ -278,7 +280,7 @@ def test_remove_all_publications_one(self): self.assertEqual(DOI_URL, links[0].target) self.collection.validate() - def test_remove_publication_forward(self): + def test_remove_publication_forward(self) -> None: ScientificExtension.ext(self.collection).apply(DOI, publications=PUBLICATIONS) ScientificExtension.ext(self.collection).remove_publication(PUBLICATIONS[0]) @@ -298,7 +300,7 @@ def test_remove_publication_forward(self): self.assertEqual(DOI_URL, links[0].target) self.collection.validate() - def test_remove_publication_reverse(self): + def test_remove_publication_reverse(self) -> None: ScientificExtension.ext(self.collection).apply(DOI, publications=PUBLICATIONS) ScientificExtension.ext(self.collection).remove_publication(PUBLICATIONS[1]) @@ -316,7 +318,7 @@ def test_remove_publication_reverse(self): self.assertEqual(DOI_URL, links[0].target) self.collection.validate() - def test_remove_all_publications_with_some(self): + def test_remove_all_publications_with_some(self) -> None: ScientificExtension.ext(self.collection).apply(DOI, publications=PUBLICATIONS) ScientificExtension.ext(self.collection).remove_publication() self.assertFalse(ScientificExtension.ext(self.collection).publications) @@ -325,7 +327,7 @@ def test_remove_all_publications_with_some(self): self.assertEqual(DOI_URL, links[0].target) self.collection.validate() - def test_remove_all_publications_with_none(self): + def test_remove_all_publications_with_none(self) -> None: ScientificExtension.ext(self.collection).apply(DOI) ScientificExtension.ext(self.collection).remove_publication() self.assertFalse(ScientificExtension.ext(self.collection).publications) diff --git a/tests/extensions/test_timestamps.py b/tests/extensions/test_timestamps.py index dad6dff3f..b01d86322 100644 --- a/tests/extensions/test_timestamps.py +++ b/tests/extensions/test_timestamps.py @@ -9,7 +9,7 @@ class TimestampsTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.maxDiff = None self.example_uri = TestCases.get_path( "data-files/timestamps/example-landsat8.json" @@ -19,10 +19,10 @@ def setUp(self): self.sample_datetime_str = "2020-01-01T00:00:00Z" self.sample_datetime = str_to_datetime(self.sample_datetime_str) - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: test_to_from_dict(self, pystac.Item, self.item_dict) - def test_apply(self): + def test_apply(self) -> None: item = next(iter(TestCases.test_case_2().get_all_items())) self.assertFalse(TimestampsExtension.has_extension(item)) @@ -58,11 +58,11 @@ def test_apply(self): for p in ("expires", "unpublished"): self.assertNotIn(p, item.properties) - def test_validate_timestamps(self): + def test_validate_timestamps(self) -> None: item = pystac.read_file(self.example_uri) item.validate() - def test_expires(self): + def test_expires(self) -> None: timestamps_item = pystac.Item.from_file(self.example_uri) # Get @@ -104,7 +104,7 @@ def test_expires(self): # Validate timestamps_item.validate() - def test_published(self): + def test_published(self) -> None: timestamps_item = pystac.Item.from_file(self.example_uri) # Get @@ -146,7 +146,7 @@ def test_published(self): # Validate timestamps_item.validate() - def test_unpublished(self): + def test_unpublished(self) -> None: timestamps_item = pystac.Item.from_file(self.example_uri) # Get diff --git a/tests/extensions/test_version.py b/tests/extensions/test_version.py index f036260e3..d61e31dda 100644 --- a/tests/extensions/test_version.py +++ b/tests/extensions/test_version.py @@ -2,6 +2,7 @@ import datetime import unittest +from typing import List, Optional import pystac from pystac.extensions import version @@ -29,39 +30,39 @@ def make_item(year: int) -> pystac.Item: class ItemVersionExtensionTest(unittest.TestCase): version: str = "1.2.3" - def setUp(self): + def setUp(self) -> None: super().setUp() self.item = make_item(2011) - def test_stac_extensions(self): + def test_stac_extensions(self) -> None: self.assertTrue(VersionExtension.has_extension(self.item)) - def test_add_version(self): + def test_add_version(self) -> None: VersionExtension.ext(self.item).apply(self.version) self.assertEqual(self.version, VersionExtension.ext(self.item).version) self.assertNotIn(version.DEPRECATED, self.item.properties) self.assertFalse(VersionExtension.ext(self.item).deprecated) self.item.validate() - def test_version_in_properties(self): + def test_version_in_properties(self) -> None: VersionExtension.ext(self.item).apply(self.version, deprecated=True) self.assertIn(version.VERSION, self.item.properties) self.assertIn(version.DEPRECATED, self.item.properties) self.item.validate() - def test_add_not_deprecated_version(self): + def test_add_not_deprecated_version(self) -> None: VersionExtension.ext(self.item).apply(self.version, deprecated=False) self.assertIn(version.DEPRECATED, self.item.properties) self.assertFalse(VersionExtension.ext(self.item).deprecated) self.item.validate() - def test_add_deprecated_version(self): + def test_add_deprecated_version(self) -> None: VersionExtension.ext(self.item).apply(self.version, deprecated=True) self.assertIn(version.DEPRECATED, self.item.properties) self.assertTrue(VersionExtension.ext(self.item).deprecated) self.item.validate() - def test_latest(self): + def test_latest(self) -> None: year = 2013 latest = make_item(year) VersionExtension.ext(self.item).apply(self.version, latest=latest) @@ -73,7 +74,7 @@ def test_latest(self): self.assertEqual(expected_href, link.get_href()) self.item.validate() - def test_predecessor(self): + def test_predecessor(self) -> None: year = 2010 predecessor = make_item(year) VersionExtension.ext(self.item).apply(self.version, predecessor=predecessor) @@ -85,7 +86,7 @@ def test_predecessor(self): self.assertEqual(expected_href, link.get_href()) self.item.validate() - def test_successor(self): + def test_successor(self) -> None: year = 2012 successor = make_item(year) VersionExtension.ext(self.item).apply(self.version, successor=successor) @@ -97,11 +98,11 @@ def test_successor(self): self.assertEqual(expected_href, link.get_href()) self.item.validate() - def test_fail_validate(self): + def test_fail_validate(self) -> None: with self.assertRaises(pystac.STACValidationError): self.item.validate() - def test_all_links(self): + def test_all_links(self) -> None: deprecated = True latest = make_item(2013) predecessor = make_item(2010) @@ -111,7 +112,7 @@ def test_all_links(self): ) self.item.validate() - def test_full_copy(self): + def test_full_copy(self) -> None: cat = TestCases.test_case_1() # Fetch two items from the catalog @@ -134,19 +135,27 @@ def test_full_copy(self): # Retrieve the copied version of the items item1_copy = cat_copy.get_item("area-1-1-imagery", recursive=True) + assert item1_copy is not None item2_copy = cat_copy.get_item("area-2-2-imagery", recursive=True) + assert item2_copy is not None # Check to see if the version links point to the instances of the # item objects as they should. - predecessor = item1_copy.get_single_link(version.PREDECESSOR).target - successor = item2_copy.get_single_link(version.SUCCESSOR).target - latest = item2_copy.get_single_link(version.LATEST).target - - self.assertIs(predecessor, item2_copy) - self.assertIs(successor, item1_copy) - self.assertIs(latest, item1_copy) - - def test_setting_none_clears_link(self): + predecessor = item1_copy.get_single_link(version.PREDECESSOR) + assert predecessor is not None + predecessor_target = predecessor.target + successor = item2_copy.get_single_link(version.SUCCESSOR) + assert successor is not None + successor_target = successor.target + latest = item2_copy.get_single_link(version.LATEST) + assert latest is not None + latest_target = latest.target + + self.assertIs(predecessor_target, item2_copy) + self.assertIs(successor_target, item1_copy) + self.assertIs(latest_target, item1_copy) + + def test_setting_none_clears_link(self) -> None: deprecated = False latest = make_item(2013) predecessor = make_item(2010) @@ -170,7 +179,7 @@ def test_setting_none_clears_link(self): self.assertEqual(0, len(links)) self.assertIsNone(VersionExtension.ext(self.item).successor) - def test_multiple_link_setting(self): + def test_multiple_link_setting(self) -> None: deprecated = False latest1 = make_item(2013) predecessor1 = make_item(2010) @@ -210,7 +219,8 @@ def make_collection(year: int) -> pystac.Collection: end = datetime.datetime(year, 1, 3, 4, 5) bboxes = [[-180.0, -90.0, 180.0, 90.0]] spatial_extent = pystac.SpatialExtent(bboxes) - temporal_extent = pystac.TemporalExtent([[start, end]]) + intervals: List[List[Optional[datetime.datetime]]] = [[start, end]] + temporal_extent = pystac.TemporalExtent(intervals) extent = pystac.Extent(spatial_extent, temporal_extent) collection = pystac.Collection(asset_id, "desc", extent) @@ -224,39 +234,39 @@ def make_collection(year: int) -> pystac.Collection: class CollectionVersionExtensionTest(unittest.TestCase): version: str = "1.2.3" - def setUp(self): + def setUp(self) -> None: super().setUp() self.collection = make_collection(2011) - def test_stac_extensions(self): + def test_stac_extensions(self) -> None: self.assertTrue(VersionExtension.has_extension(self.collection)) - def test_add_version(self): + def test_add_version(self) -> None: VersionExtension.ext(self.collection).apply(self.version) self.assertEqual(self.version, VersionExtension.ext(self.collection).version) self.assertNotIn(version.DEPRECATED, self.collection.extra_fields) self.assertFalse(VersionExtension.ext(self.collection).deprecated) self.collection.validate() - def test_version_deprecated(self): + def test_version_deprecated(self) -> None: VersionExtension.ext(self.collection).apply(self.version, deprecated=True) self.assertIn(version.VERSION, self.collection.extra_fields) self.assertIn(version.DEPRECATED, self.collection.extra_fields) self.collection.validate() - def test_add_not_deprecated_version(self): + def test_add_not_deprecated_version(self) -> None: VersionExtension.ext(self.collection).apply(self.version, deprecated=False) self.assertIn(version.DEPRECATED, self.collection.extra_fields) self.assertFalse(VersionExtension.ext(self.collection).deprecated) self.collection.validate() - def test_add_deprecated_version(self): + def test_add_deprecated_version(self) -> None: VersionExtension.ext(self.collection).apply(self.version, deprecated=True) self.assertIn(version.DEPRECATED, self.collection.extra_fields) self.assertTrue(VersionExtension.ext(self.collection).deprecated) self.collection.validate() - def test_latest(self): + def test_latest(self) -> None: year = 2013 latest = make_collection(year) VersionExtension.ext(self.collection).apply(self.version, latest=latest) @@ -268,7 +278,7 @@ def test_latest(self): self.assertEqual(expected_href, link.get_href()) self.collection.validate() - def test_predecessor(self): + def test_predecessor(self) -> None: year = 2010 predecessor = make_collection(year) VersionExtension.ext(self.collection).apply( @@ -282,7 +292,7 @@ def test_predecessor(self): self.assertEqual(expected_href, link.get_href()) self.collection.validate() - def test_successor(self): + def test_successor(self) -> None: year = 2012 successor = make_collection(year) VersionExtension.ext(self.collection).apply(self.version, successor=successor) @@ -294,11 +304,11 @@ def test_successor(self): self.assertEqual(expected_href, link.get_href()) self.collection.validate() - def test_fail_validate(self): + def test_fail_validate(self) -> None: with self.assertRaises(pystac.STACValidationError): self.collection.validate() - def test_validate_all(self): + def test_validate_all(self) -> None: deprecated = True latest = make_collection(2013) predecessor = make_collection(2010) @@ -308,7 +318,7 @@ def test_validate_all(self): ) self.collection.validate() - def test_full_copy(self): + def test_full_copy(self) -> None: cat = TestCases.test_case_1() # Fetch two collections from the catalog @@ -330,19 +340,27 @@ def test_full_copy(self): # Retrieve the copied version of the items col1_copy = cat_copy.get_child("area-1-1", recursive=True) + assert col1_copy is not None col2_copy = cat_copy.get_child("area-2-2", recursive=True) + assert col2_copy is not None # Check to see if the version links point to the instances of the # col objects as they should. - predecessor = col1_copy.get_single_link(version.PREDECESSOR).target - successor = col2_copy.get_single_link(version.SUCCESSOR).target - latest = col2_copy.get_single_link(version.LATEST).target - - self.assertIs(predecessor, col2_copy) - self.assertIs(successor, col1_copy) - self.assertIs(latest, col1_copy) - - def test_setting_none_clears_link(self): + predecessor = col1_copy.get_single_link(version.PREDECESSOR) + assert predecessor is not None + predecessor_target = predecessor.target + successor = col2_copy.get_single_link(version.SUCCESSOR) + assert successor is not None + successor_target = successor.target + latest = col2_copy.get_single_link(version.LATEST) + assert latest is not None + latest_target = latest.target + + self.assertIs(predecessor_target, col2_copy) + self.assertIs(successor_target, col1_copy) + self.assertIs(latest_target, col1_copy) + + def test_setting_none_clears_link(self) -> None: deprecated = False latest = make_collection(2013) predecessor = make_collection(2010) @@ -366,7 +384,7 @@ def test_setting_none_clears_link(self): self.assertEqual(0, len(links)) self.assertIsNone(VersionExtension.ext(self.collection).successor) - def test_multiple_link_setting(self): + def test_multiple_link_setting(self) -> None: deprecated = False latest1 = make_collection(2013) predecessor1 = make_collection(2010) diff --git a/tests/extensions/test_view.py b/tests/extensions/test_view.py index ee96a7107..a4956bb60 100644 --- a/tests/extensions/test_view.py +++ b/tests/extensions/test_view.py @@ -7,16 +7,16 @@ class ViewTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.maxDiff = None self.example_uri = TestCases.get_path("data-files/view/example-landsat8.json") - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: with open(self.example_uri) as f: d = json.load(f) test_to_from_dict(self, pystac.Item, d) - def test_apply(self): + def test_apply(self) -> None: item = next(iter(TestCases.test_case_2().get_all_items())) self.assertFalse(ViewExtension.has_extension(item)) @@ -35,17 +35,18 @@ def test_apply(self): self.assertEqual(ViewExtension.ext(item).sun_azimuth, 4.0) self.assertEqual(ViewExtension.ext(item).sun_elevation, 5.0) - def test_validate_view(self): + def test_validate_view(self) -> None: item = pystac.Item.from_file(self.example_uri) self.assertTrue(ViewExtension.has_extension(item)) item.validate() - def test_off_nadir(self): + def test_off_nadir(self) -> None: view_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("view:off_nadir", view_item.properties) view_off_nadir = ViewExtension.ext(view_item).off_nadir + assert view_off_nadir is not None self.assertEqual(view_off_nadir, view_item.properties["view:off_nadir"]) # Set @@ -73,12 +74,13 @@ def test_off_nadir(self): # Validate view_item.validate() - def test_incidence_angle(self): + def test_incidence_angle(self) -> None: view_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("view:incidence_angle", view_item.properties) view_incidence_angle = ViewExtension.ext(view_item).incidence_angle + assert view_incidence_angle is not None self.assertEqual( view_incidence_angle, view_item.properties["view:incidence_angle"] ) @@ -110,12 +112,13 @@ def test_incidence_angle(self): # Validate view_item.validate() - def test_azimuth(self): + def test_azimuth(self) -> None: view_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("view:azimuth", view_item.properties) view_azimuth = ViewExtension.ext(view_item).azimuth + assert view_azimuth is not None self.assertEqual(view_azimuth, view_item.properties["view:azimuth"]) # Set @@ -143,12 +146,13 @@ def test_azimuth(self): # Validate view_item.validate() - def test_sun_azimuth(self): + def test_sun_azimuth(self) -> None: view_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("view:sun_azimuth", view_item.properties) view_sun_azimuth = ViewExtension.ext(view_item).sun_azimuth + assert view_sun_azimuth is not None self.assertEqual(view_sun_azimuth, view_item.properties["view:sun_azimuth"]) # Set @@ -178,12 +182,13 @@ def test_sun_azimuth(self): # Validate view_item.validate() - def test_sun_elevation(self): + def test_sun_elevation(self) -> None: view_item = pystac.Item.from_file(self.example_uri) # Get self.assertIn("view:sun_elevation", view_item.properties) view_sun_elevation = ViewExtension.ext(view_item).sun_elevation + assert view_sun_elevation is not None self.assertEqual(view_sun_elevation, view_item.properties["view:sun_elevation"]) # Set diff --git a/tests/serialization/test_identify.py b/tests/serialization/test_identify.py index 97c1e6436..829f16cc7 100644 --- a/tests/serialization/test_identify.py +++ b/tests/serialization/test_identify.py @@ -14,10 +14,10 @@ class IdentifyTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.examples = TestCases.get_examples_info() - def test_identify(self): + def test_identify(self) -> None: collection_cache = CollectionCache() for example in self.examples: with self.subTest(example.path): @@ -49,7 +49,7 @@ def test_identify(self): class VersionTest(unittest.TestCase): - def test_version_ordering(self): + def test_version_ordering(self) -> None: self.assertEqual(STACVersionID("0.9.0"), STACVersionID("0.9.0")) self.assertFalse(STACVersionID("0.9.0") < STACVersionID("0.9.0")) self.assertFalse(STACVersionID("0.9.0") != STACVersionID("0.9.0")) @@ -59,12 +59,12 @@ def test_version_ordering(self): self.assertFalse(STACVersionID("0.9.0") > "0.9.0") # type:ignore self.assertTrue(STACVersionID("0.9.0") <= "0.9.0") # type:ignore self.assertTrue( - STACVersionID("1.0.0-beta.1") + STACVersionID("1.0.0-beta.1") # type:ignore <= STACVersionID("1.0.0-beta.2") # type:ignore ) self.assertFalse(STACVersionID("1.0.0") < STACVersionID("1.0.0-beta.2")) - def test_version_range_ordering(self): + def test_version_range_ordering(self) -> None: version_range = STACVersionRange("0.9.0", "1.0.0-beta.2") self.assertIsInstance(str(version_range), str) self.assertTrue(version_range.contains("1.0.0-beta.1")) diff --git a/tests/serialization/test_migrate.py b/tests/serialization/test_migrate.py index c4c9ed6f9..98ba4b8fa 100644 --- a/tests/serialization/test_migrate.py +++ b/tests/serialization/test_migrate.py @@ -16,10 +16,10 @@ class MigrateTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.examples = [e for e in TestCases.get_examples_info()] - def test_migrate(self): + def test_migrate(self) -> None: collection_cache = CollectionCache() for example in self.examples: with self.subTest(example.path): @@ -55,7 +55,7 @@ def test_migrate(self): pystac.read_dict(migrated_d, href=path), pystac.STACObject ) - def test_migrates_removed_extension(self): + def test_migrates_removed_extension(self) -> None: item = pystac.Item.from_file( TestCases.get_path( "data-files/examples/0.7.0/extensions/sar/" "examples/sentinel1.json" @@ -67,7 +67,7 @@ def test_migrates_removed_extension(self): str_to_datetime("2018-11-03T23:58:55.121559Z"), ) - def test_migrates_added_extension(self): + def test_migrates_added_extension(self) -> None: item = pystac.Item.from_file( TestCases.get_path( "data-files/examples/0.8.1/item-spec/" "examples/planet-sample.json" @@ -79,7 +79,7 @@ def test_migrates_added_extension(self): self.assertEqual(view_ext.sun_elevation, 58.8) self.assertEqual(view_ext.off_nadir, 1) - def test_migrates_renamed_extension(self): + def test_migrates_renamed_extension(self) -> None: collection = pystac.Collection.from_file( TestCases.get_path( "data-files/examples/0.9.0/extensions/asset/" diff --git a/tests/test_cache.py b/tests/test_cache.py index 1fcc75965..70e0bc886 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -20,7 +20,7 @@ def create_catalog(suffix: Any, include_href: bool = True) -> pystac.Catalog: class ResolvedObjectCacheTest(unittest.TestCase): - def tests_get_or_cache_returns_previously_cached_href(self): + def tests_get_or_cache_returns_previously_cached_href(self) -> None: cache = ResolvedObjectCache() cat = create_catalog(1) cache_result_1 = cache.get_or_cache(cat) @@ -30,7 +30,7 @@ def tests_get_or_cache_returns_previously_cached_href(self): cache_result_2 = cache.get_or_cache(identical_cat) self.assertIs(cache_result_2, cat) - def test_get_or_cache_returns_previously_cached_id(self): + def test_get_or_cache_returns_previously_cached_id(self) -> None: cache = ResolvedObjectCache() cat = create_catalog(1, include_href=False) cache_result_1 = cache.get_or_cache(cat) @@ -42,7 +42,7 @@ def test_get_or_cache_returns_previously_cached_id(self): class ResolvedObjectCollectionCacheTest(unittest.TestCase): - def test_merge(self): + def test_merge(self) -> None: cat1 = create_catalog(1, include_href=False) cat2 = create_catalog(2) cat3 = create_catalog(3, include_href=False) @@ -79,7 +79,7 @@ def test_merge(self): ) self.assertIs(merged.get_by_href(get_opt(cat2.get_self_href())), cat2) - def test_cache(self): + def test_cache(self) -> None: cache = ResolvedObjectCache().as_collection_cache() collection = TestCases.test_case_8() collection_json = collection.to_dict() diff --git a/tests/test_catalog.py b/tests/test_catalog.py index d7ad5a3a8..e38fd15e9 100644 --- a/tests/test_catalog.py +++ b/tests/test_catalog.py @@ -22,7 +22,7 @@ class CatalogTypeTest(unittest.TestCase): - def test_determine_type_for_absolute_published(self): + def test_determine_type_for_absolute_published(self) -> None: cat = TestCases.test_case_1() with TemporaryDirectory() as tmp_dir: cat.normalize_and_save(tmp_dir, catalog_type=CatalogType.ABSOLUTE_PUBLISHED) @@ -33,7 +33,7 @@ def test_determine_type_for_absolute_published(self): catalog_type = CatalogType.determine_type(cat_json) self.assertEqual(catalog_type, CatalogType.ABSOLUTE_PUBLISHED) - def test_determine_type_for_relative_published(self): + def test_determine_type_for_relative_published(self) -> None: cat = TestCases.test_case_2() with TemporaryDirectory() as tmp_dir: cat.normalize_and_save(tmp_dir, catalog_type=CatalogType.RELATIVE_PUBLISHED) @@ -44,14 +44,14 @@ def test_determine_type_for_relative_published(self): catalog_type = CatalogType.determine_type(cat_json) self.assertEqual(catalog_type, CatalogType.RELATIVE_PUBLISHED) - def test_determine_type_for_self_contained(self): + def test_determine_type_for_self_contained(self) -> None: cat_json = pystac.StacIO.default().read_json( TestCases.get_path("data-files/catalogs/test-case-1/catalog.json") ) catalog_type = CatalogType.determine_type(cat_json) self.assertEqual(catalog_type, CatalogType.SELF_CONTAINED) - def test_determine_type_for_unknown(self): + def test_determine_type_for_unknown(self) -> None: catalog = Catalog(id="test", description="test desc") subcat = Catalog(id="subcat", description="subcat desc") catalog.add_child(subcat) @@ -62,7 +62,7 @@ def test_determine_type_for_unknown(self): class CatalogTest(unittest.TestCase): - def test_create_and_read(self): + def test_create_and_read(self) -> None: with TemporaryDirectory() as tmp_dir: cat_dir = os.path.join(tmp_dir, "catalog") catalog = TestCases.test_case_1() @@ -80,7 +80,7 @@ def test_create_and_read(self): self.assertEqual(len(list(items)), 8) - def test_read_remote(self): + def test_read_remote(self) -> None: # TODO: Move this URL to the main stac-spec repo once the example JSON is fixed. catalog_url = ( "https://raw.githubusercontent.com/lossyrob/stac-spec/" @@ -90,10 +90,11 @@ def test_read_remote(self): cat = Catalog.from_file(catalog_url) zanzibar = cat.get_child("zanzibar-collection") + assert zanzibar is not None self.assertEqual(len(list(zanzibar.get_items())), 2) - def test_clear_items_removes_from_cache(self): + def test_clear_items_removes_from_cache(self) -> None: catalog = Catalog(id="test", description="test") subcat = Catalog(id="subcat", description="test") catalog.add_child(subcat) @@ -138,7 +139,7 @@ def test_clear_items_removes_from_cache(self): self.assertEqual(len(items), 1) self.assertEqual(items[0].properties["key"], "three") - def test_clear_children_removes_from_cache(self): + def test_clear_children_removes_from_cache(self) -> None: catalog = Catalog(id="test", description="test") subcat = Catalog(id="subcat", description="test") catalog.add_child(subcat) @@ -163,7 +164,7 @@ def test_clear_children_removes_from_cache(self): self.assertEqual(len(children), 1) self.assertEqual(children[0].description, "test3") - def test_clear_children_sets_parent_and_root_to_None(self): + def test_clear_children_sets_parent_and_root_to_None(self) -> None: catalog = Catalog(id="test", description="test") subcat1 = Catalog(id="subcat", description="test") subcat2 = Catalog(id="subcat2", description="test2") @@ -184,35 +185,35 @@ def test_clear_children_sets_parent_and_root_to_None(self): self.assertIsNone(subcat1.get_root()) self.assertIsNone(subcat2.get_root()) - def test_add_child_throws_if_item(self): + def test_add_child_throws_if_item(self) -> None: cat = TestCases.test_case_1() item = next(iter(cat.get_all_items())) with self.assertRaises(pystac.STACError): cat.add_child(item) # type:ignore - def test_add_item_throws_if_child(self): + def test_add_item_throws_if_child(self) -> None: cat = TestCases.test_case_1() child = next(iter(cat.get_children())) with self.assertRaises(pystac.STACError): cat.add_item(child) # type:ignore - def test_get_child_returns_none_if_not_found(self): + def test_get_child_returns_none_if_not_found(self) -> None: cat = TestCases.test_case_1() child = cat.get_child("thisshouldnotbeachildid", recursive=True) self.assertIsNone(child) - def test_get_item_returns_none_if_not_found(self): + def test_get_item_returns_none_if_not_found(self) -> None: cat = TestCases.test_case_1() item = cat.get_item("thisshouldnotbeanitemid", recursive=True) self.assertIsNone(item) - def test_sets_catalog_type(self): + def test_sets_catalog_type(self) -> None: cat = TestCases.test_case_1() self.assertEqual(cat.catalog_type, CatalogType.SELF_CONTAINED) - def test_walk_iterates_correctly(self): - def test_catalog(cat: Catalog): + def test_walk_iterates_correctly(self) -> None: + def test_catalog(cat: Catalog) -> None: expected_catalog_iterations = 1 actual_catalog_iterations = 0 with self.subTest(title="Testing catalog {}".format(cat.id)): @@ -236,7 +237,7 @@ def test_catalog(cat: Catalog): for cat in TestCases.all_test_catalogs(): test_catalog(cat) - def test_clone_generates_correct_links(self): + def test_clone_generates_correct_links(self) -> None: catalogs = TestCases.all_test_catalogs() for catalog in catalogs: @@ -279,7 +280,7 @@ def test_clone_generates_correct_links(self): ), ) - def test_save_uses_previous_catalog_type(self): + def test_save_uses_previous_catalog_type(self) -> None: catalog = TestCases.test_case_1() assert catalog.catalog_type == CatalogType.SELF_CONTAINED with TemporaryDirectory() as tmp_dir: @@ -290,17 +291,19 @@ def test_save_uses_previous_catalog_type(self): cat2 = pystac.Catalog.from_file(href) self.assertEqual(cat2.catalog_type, CatalogType.SELF_CONTAINED) - def test_clone_uses_previous_catalog_type(self): + def test_clone_uses_previous_catalog_type(self) -> None: catalog = TestCases.test_case_1() assert catalog.catalog_type == CatalogType.SELF_CONTAINED clone = catalog.clone() self.assertEqual(clone.catalog_type, CatalogType.SELF_CONTAINED) - def test_normalize_hrefs_sets_all_hrefs(self): + def test_normalize_hrefs_sets_all_hrefs(self) -> None: catalog = TestCases.test_case_1() catalog.normalize_hrefs("http://example.com") for root, _, items in catalog.walk(): - self.assertTrue(root.get_self_href().startswith("http://example.com")) + self_href = root.get_self_href() + assert self_href is not None + self.assertTrue(self_href.startswith("http://example.com")) for link in root.links: if link.is_resolved(): target_href = cast(pystac.STACObject, link.target).self_href @@ -315,13 +318,15 @@ def test_normalize_hrefs_sets_all_hrefs(self): for item in items: self.assertIn("http://example.com", item.self_href) - def test_normalize_hrefs_makes_absolute_href(self): + def test_normalize_hrefs_makes_absolute_href(self) -> None: catalog = TestCases.test_case_1() catalog.normalize_hrefs("./relativepath") abspath = os.path.abspath("./relativepath") - self.assertTrue(catalog.get_self_href().startswith(abspath)) + self_href = catalog.get_self_href() + assert self_href is not None + self.assertTrue(self_href.startswith(abspath)) - def test_normalize_href_works_with_label_source_links(self): + def test_normalize_href_works_with_label_source_links(self) -> None: catalog = TestCases.test_case_1() catalog.normalize_hrefs("http://example.com") item = catalog.get_item("area-1-1-labels", recursive=True) @@ -333,7 +338,7 @@ def test_normalize_href_works_with_label_source_links(self): "area-1-1-imagery/area-1-1-imagery.json", ) - def test_generate_subcatalogs_works_with_custom_properties(self): + def test_generate_subcatalogs_works_with_custom_properties(self) -> None: catalog = TestCases.test_case_8() defaults = {"pl:item_type": "PlanetScope"} catalog.generate_subcatalogs( @@ -341,11 +346,12 @@ def test_generate_subcatalogs_works_with_custom_properties(self): ) month_cat = catalog.get_child("8", recursive=True) + assert month_cat is not None type_cats = set([cat.id for cat in month_cat.get_children()]) self.assertEqual(type_cats, set(["PSScene4Band", "SkySatScene", "PlanetScope"])) - def test_generate_subcatalogs_does_not_change_item_count(self): + def test_generate_subcatalogs_does_not_change_item_count(self) -> None: catalog = TestCases.test_case_7() item_counts = { @@ -366,7 +372,7 @@ def test_generate_subcatalogs_does_not_change_item_count(self): actual, expected, msg=" for child '{}'".format(child.id) ) - def test_generate_subcatalogs_can_be_applied_multiple_times(self): + def test_generate_subcatalogs_can_be_applied_multiple_times(self) -> None: catalog = TestCases.test_case_8() _ = catalog.generate_subcatalogs("${year}/${month}") @@ -385,7 +391,7 @@ def test_generate_subcatalogs_can_be_applied_multiple_times(self): msg=" for item '{}'".format(item.id), ) - def test_generate_subcatalogs_works_after_adding_more_items(self): + def test_generate_subcatalogs_works_after_adding_more_items(self) -> None: catalog = Catalog(id="test", description="Test") properties = dict(property1="A", property2=1) catalog.add_item( @@ -410,11 +416,17 @@ def test_generate_subcatalogs_works_after_adding_more_items(self): catalog.generate_subcatalogs("${property1}/${property2}") catalog.normalize_hrefs("/tmp") - item1_parent = catalog.get_item("item1", recursive=True).get_parent() - item2_parent = catalog.get_item("item2", recursive=True).get_parent() + item1 = catalog.get_item("item1", recursive=True) + assert item1 is not None + item1_parent = item1.get_parent() + assert item1_parent is not None + item2 = catalog.get_item("item2", recursive=True) + assert item2 is not None + item2_parent = item2.get_parent() + assert item2_parent is not None self.assertEqual(item1_parent.get_self_href(), item2_parent.get_self_href()) - def test_generate_subcatalogs_works_for_branched_subcatalogs(self): + def test_generate_subcatalogs_works_for_branched_subcatalogs(self) -> None: catalog = Catalog(id="test", description="Test") item_properties = [ dict(property1="A", property2=1, property3="i"), # add 3 subcats @@ -439,7 +451,7 @@ def test_generate_subcatalogs_works_for_branched_subcatalogs(self): expected_subcats = {"A", "B", "1", "2", "i", "j"} self.assertSetEqual(actual_subcats, expected_subcats) - def test_generate_subcatalogs_works_for_subcatalogs_with_same_ids(self): + def test_generate_subcatalogs_works_for_subcatalogs_with_same_ids(self) -> None: catalog = Catalog(id="test", description="Test") item_properties = [ dict(property1=1, property2=1), # add 2 subcats @@ -462,12 +474,14 @@ def test_generate_subcatalogs_works_for_subcatalogs_with_same_ids(self): catalog.normalize_hrefs("/") for item in catalog.get_all_items(): - parent_href = item.get_parent().self_href + item_parent = item.get_parent() + assert item_parent is not None + parent_href = item_parent.self_href path_to_parent, _ = os.path.split(parent_href) subcats = [el for el in path_to_parent.split("/") if el] self.assertEqual(len(subcats), 2, msg=" for item '{}'".format(item.id)) - def test_map_items(self): + def test_map_items(self) -> None: def item_mapper(item: pystac.Item) -> pystac.Item: item.properties["ITEM_MAPPER"] = "YEP" return item @@ -488,7 +502,7 @@ def item_mapper(item: pystac.Item) -> pystac.Item: for item in catalog.get_all_items(): self.assertFalse("ITEM_MAPPER" in item.properties) - def test_map_items_multiple(self): + def test_map_items_multiple(self) -> None: def item_mapper(item: pystac.Item) -> List[pystac.Item]: item2 = item.clone() item2.id = item2.id + "_2" @@ -530,7 +544,7 @@ def item_mapper(item: pystac.Item) -> List[pystac.Item]: or ("ITEM_MAPPER_2" in item.properties) ) - def test_map_items_multiple_2(self): + def test_map_items_multiple_2(self) -> None: catalog = Catalog(id="test-1", description="Test1") item1 = Item( id="item1", @@ -592,7 +606,7 @@ def create_label_item(item: pystac.Item) -> List[pystac.Item]: items = new_catalog.get_all_items() self.assertTrue(len(list(items)) == 4) - def test_map_assets_single(self): + def test_map_assets_single(self) -> None: changed_asset = "d43bead8-e3f8-4c51-95d6-e24e750a402b" def asset_mapper(key: str, asset: pystac.Asset) -> pystac.Asset: @@ -621,7 +635,7 @@ def asset_mapper(key: str, asset: pystac.Asset) -> pystac.Asset: self.assertNotEqual(asset.title, "NEW TITLE") self.assertTrue(found) - def test_map_assets_tup(self): + def test_map_assets_tup(self) -> None: changed_assets: List[str] = [] def asset_mapper( @@ -658,7 +672,7 @@ def asset_mapper( self.assertTrue(found) self.assertTrue(not_found) - def test_map_assets_multi(self): + def test_map_assets_multi(self) -> None: changed_assets = [] def asset_mapper( @@ -703,17 +717,19 @@ def asset_mapper( self.assertTrue(found2) self.assertTrue(not_found) - def test_make_all_asset_hrefs_absolute(self): + def test_make_all_asset_hrefs_absolute(self) -> None: cat = TestCases.test_case_2() cat.make_all_asset_hrefs_absolute() item = cat.get_item("cf73ec1a-d790-4b59-b077-e101738571ed", recursive=True) + assert item is not None href = item.assets["cf73ec1a-d790-4b59-b077-e101738571ed"].href self.assertTrue(is_absolute_href(href)) - def test_make_all_asset_hrefs_relative(self): + def test_make_all_asset_hrefs_relative(self) -> None: cat = TestCases.test_case_2() item = cat.get_item("cf73ec1a-d790-4b59-b077-e101738571ed", recursive=True) + assert item is not None asset = item.assets["cf73ec1a-d790-4b59-b077-e101738571ed"] original_href = asset.href cat.make_all_asset_hrefs_absolute() @@ -725,8 +741,8 @@ def test_make_all_asset_hrefs_relative(self): self.assertFalse(is_absolute_href(asset.href)) self.assertEqual(asset.href, original_href) - def test_make_all_links_relative_or_absolute(self): - def check_all_relative(cat: Catalog): + def test_make_all_links_relative_or_absolute(self) -> None: + def check_all_relative(cat: Catalog) -> None: for root, catalogs, items in cat.walk(): for link in root.links: if link.rel in HIERARCHICAL_LINKS: @@ -736,7 +752,7 @@ def check_all_relative(cat: Catalog): if link.rel in HIERARCHICAL_LINKS: self.assertFalse(is_absolute_href(link.href)) - def check_all_absolute(cat: Catalog): + def check_all_absolute(cat: Catalog) -> None: for root, catalogs, items in cat.walk(): for link in root.links: self.assertTrue(is_absolute_href(link.href)) @@ -755,7 +771,7 @@ def check_all_absolute(cat: Catalog): c2.catalog_type = CatalogType.ABSOLUTE_PUBLISHED check_all_absolute(c2) - def test_full_copy_and_normalize_works_with_created_stac(self): + def test_full_copy_and_normalize_works_with_created_stac(self) -> None: cat = TestCases.test_case_3() cat_copy = cat.full_copy() cat_copy.normalize_hrefs("http://example.com") @@ -768,7 +784,7 @@ def test_full_copy_and_normalize_works_with_created_stac(self): if link.rel != "self": self.assertIsNot(link.get_href(), None) - def test_extra_fields(self): + def test_extra_fields(self) -> None: catalog = TestCases.test_case_1() catalog.extra_fields["type"] = "FeatureCollection" @@ -785,7 +801,7 @@ def test_extra_fields(self): self.assertTrue("type" in read_cat.extra_fields) self.assertEqual(read_cat.extra_fields["type"], "FeatureCollection") - def test_validate_all(self): + def test_validate_all(self) -> None: for cat in TestCases.all_test_catalogs(): with self.subTest(cat.id): # If hrefs are not set, it will fail validation. @@ -796,6 +812,7 @@ def test_validate_all(self): # Make one invalid, write it off, read it in, ensure it throws cat = TestCases.test_case_1() item = cat.get_item("area-1-1-labels", recursive=True) + assert item is not None item.geometry = {"type": "INVALID", "coordinates": "NONE"} with TemporaryDirectory() as tmp_dir: cat.normalize_hrefs(tmp_dir) @@ -806,13 +823,14 @@ def test_validate_all(self): with self.assertRaises(pystac.STACValidationError): cat2.validate_all() - def test_set_hrefs_manually(self): + def test_set_hrefs_manually(self) -> None: catalog = TestCases.test_case_1() # Modify the datetimes year = 2004 month = 2 for item in catalog.get_all_items(): + assert item.datetime is not None item.datetime = item.datetime.replace(year=year, month=month) year += 1 month += 1 @@ -832,6 +850,7 @@ def test_set_hrefs_manually(self): # Set each item's HREF based on it's datetime for item in items: + assert item.datetime is not None item_href = "{}/{}-{}/{}.json".format( root_dir, item.datetime.year, item.datetime.month, item.id ) @@ -854,12 +873,15 @@ def test_set_hrefs_manually(self): os.path.join(d, root.id, root.DEFAULT_FILE_NAME), ) for item in items: + assert item.datetime is not None end = "{}-{}/{}.json".format( item.datetime.year, item.datetime.month, item.id ) - self.assertTrue(item.get_self_href().endswith(end)) + self_href = item.get_self_href() + assert self_href is not None + self.assertTrue(self_href.endswith(end)) - def test_collections_cache_correctly(self): + def test_collections_cache_correctly(self) -> None: catalogs = TestCases.all_test_catalogs() mock_io = MockStacIO() for cat in catalogs: @@ -888,7 +910,7 @@ def test_collections_cache_correctly(self): ), ) - def test_reading_iterating_and_writing_works_as_expected(self): + def test_reading_iterating_and_writing_works_as_expected(self) -> None: """Test case to cover issue #88""" stac_uri = "tests/data-files/catalogs/test-case-6/catalog.json" cat = Catalog.from_file(stac_uri) @@ -910,11 +932,11 @@ def test_reading_iterating_and_writing_works_as_expected(self): # Iterate again over the items. This would fail in #88 pass - def test_get_children_cbers(self): + def test_get_children_cbers(self) -> None: cat = TestCases.test_case_6() self.assertEqual(len(list(cat.get_children())), 4) - def test_resolve_planet(self): + def test_resolve_planet(self) -> None: """Test against a bug that caused infinite recursion during link resolution""" cat = TestCases.test_case_8() for root, _, items in cat.walk(): @@ -922,7 +944,7 @@ def test_resolve_planet(self): item.resolve_links() root.resolve_links() - def test_handles_children_with_same_id(self): + def test_handles_children_with_same_id(self) -> None: # This catalog has the root and child collection share an ID. cat = pystac.Catalog.from_file( TestCases.get_path("data-files/invalid/shared-id/catalog.json") @@ -931,7 +953,7 @@ def test_handles_children_with_same_id(self): self.assertEqual(len(items), 1) - def test_catalog_with_href_caches_by_href(self): + def test_catalog_with_href_caches_by_href(self) -> None: cat = TestCases.test_case_1() cache = cat._resolved_objects @@ -941,7 +963,7 @@ def test_catalog_with_href_caches_by_href(self): class FullCopyTest(unittest.TestCase): - def check_link(self, link: pystac.Link, tag: str): + def check_link(self, link: pystac.Link, tag: str) -> None: if link.is_resolved(): target_href: str = cast(pystac.STACObject, link.target).self_href else: @@ -951,11 +973,11 @@ def check_link(self, link: pystac.Link, tag: str): '[{}] {} does not contain "{}"'.format(link.rel, target_href, tag), ) - def check_item(self, item: Item, tag: str): + def check_item(self, item: Item, tag: str) -> None: for link in item.links: self.check_link(link, tag) - def check_catalog(self, c: Catalog, tag: str): + def check_catalog(self, c: Catalog, tag: str) -> None: self.assertEqual(len(c.get_links("root")), 1) for link in c.links: @@ -967,7 +989,7 @@ def check_catalog(self, c: Catalog, tag: str): for item in c.get_items(): self.check_item(item, tag) - def test_full_copy_1(self): + def test_full_copy_1(self) -> None: with TemporaryDirectory() as tmp_dir: cat = Catalog(id="test", description="test catalog") @@ -988,7 +1010,7 @@ def test_full_copy_1(self): self.check_catalog(cat, "source") self.check_catalog(cat2, "dest") - def test_full_copy_2(self): + def test_full_copy_2(self) -> None: with TemporaryDirectory() as tmp_dir: cat = Catalog(id="test", description="test catalog") image_item = Item( @@ -1035,7 +1057,7 @@ def test_full_copy_2(self): self.check_catalog(cat, "source") self.check_catalog(cat2, "dest") - def test_full_copy_3(self): + def test_full_copy_3(self) -> None: with TemporaryDirectory() as tmp_dir: root_cat = TestCases.test_case_1() root_cat.normalize_hrefs( @@ -1049,7 +1071,7 @@ def test_full_copy_3(self): self.check_catalog(root_cat, "source") self.check_catalog(cat2, "dest") - def test_full_copy_4(self): + def test_full_copy_4(self) -> None: with TemporaryDirectory() as tmp_dir: root_cat = TestCases.test_case_2() root_cat.normalize_hrefs( @@ -1065,6 +1087,7 @@ def test_full_copy_4(self): # Check that the relative asset link was saved correctly in the copy. item = cat2.get_item("cf73ec1a-d790-4b59-b077-e101738571ed", recursive=True) + assert item is not None href = item.assets[ "cf73ec1a-d790-4b59-b077-e101738571ed" diff --git a/tests/test_collection.py b/tests/test_collection.py index 3ae88ef2c..cb341f7a0 100644 --- a/tests/test_collection.py +++ b/tests/test_collection.py @@ -16,7 +16,7 @@ class CollectionTest(unittest.TestCase): - def test_spatial_extent_from_coordinates(self): + def test_spatial_extent_from_coordinates(self) -> None: extent = SpatialExtent.from_coordinates(ARBITRARY_GEOM["coordinates"]) self.assertEqual(len(extent.bboxes), 1) @@ -25,13 +25,13 @@ def test_spatial_extent_from_coordinates(self): for x in bbox: self.assertTrue(type(x) is float) - def test_read_eo_items_are_heritable(self): + def test_read_eo_items_are_heritable(self) -> None: cat = TestCases.test_case_5() item = next(iter(cat.get_all_items())) self.assertTrue(EOExtension.has_extension(item)) - def test_save_uses_previous_catalog_type(self): + def test_save_uses_previous_catalog_type(self) -> None: collection = TestCases.test_case_8() assert collection.STAC_OBJECT_TYPE == pystac.STACObjectType.COLLECTION self.assertEqual(collection.catalog_type, CatalogType.SELF_CONTAINED) @@ -43,15 +43,18 @@ def test_save_uses_previous_catalog_type(self): collection2 = pystac.Collection.from_file(href) self.assertEqual(collection2.catalog_type, CatalogType.SELF_CONTAINED) - def test_clone_uses_previous_catalog_type(self): + def test_clone_uses_previous_catalog_type(self) -> None: catalog = TestCases.test_case_8() assert catalog.catalog_type == CatalogType.SELF_CONTAINED clone = catalog.clone() self.assertEqual(clone.catalog_type, CatalogType.SELF_CONTAINED) - def test_multiple_extents(self): + def test_multiple_extents(self) -> None: cat1 = TestCases.test_case_1() - col1 = cat1.get_child("country-1").get_child("area-1-1") + country = cat1.get_child("country-1") + assert country is not None + col1 = country.get_child("area-1-1") + assert col1 is not None col1.validate() self.assertIsInstance(col1, Collection) validate_dict(col1.to_dict(), pystac.STACObjectType.COLLECTION) @@ -74,9 +77,10 @@ def test_multiple_extents(self): cloned_ext = ext.clone() self.assertDictEqual(cloned_ext.to_dict(), multi_ext_dict["extent"]) - def test_extra_fields(self): + def test_extra_fields(self) -> None: catalog = TestCases.test_case_2() collection = catalog.get_child("1a8c1632-fa91-4a62-b33e-3a87c2ebdf16") + assert collection is not None collection.extra_fields["test"] = "extra" @@ -92,7 +96,7 @@ def test_extra_fields(self): self.assertTrue("test" in read_col.extra_fields) self.assertEqual(read_col.extra_fields["test"], "extra") - def test_update_extents(self): + def test_update_extents(self) -> None: catalog = TestCases.test_case_2() base_collection = catalog.get_child("1a8c1632-fa91-4a62-b33e-3a87c2ebdf16") @@ -149,7 +153,7 @@ def test_update_extents(self): collection.extent.temporal.intervals, ) - def test_supplying_href_in_init_does_not_fail(self): + def test_supplying_href_in_init_does_not_fail(self) -> None: test_href = "http://example.com/collection.json" spatial_extent = SpatialExtent(bboxes=[ARBITRARY_BBOX]) temporal_extent = TemporalExtent(intervals=[[TEST_DATETIME, None]]) @@ -161,7 +165,7 @@ def test_supplying_href_in_init_does_not_fail(self): self.assertEqual(collection.get_self_href(), test_href) - def test_collection_with_href_caches_by_href(self): + def test_collection_with_href_caches_by_href(self) -> None: collection = pystac.Collection.from_file( TestCases.get_path("data-files/examples/hand-0.8.1/collection.json") ) @@ -173,7 +177,7 @@ def test_collection_with_href_caches_by_href(self): class ExtentTest(unittest.TestCase): - def test_spatial_allows_single_bbox(self): + def test_spatial_allows_single_bbox(self) -> None: temporal_extent = TemporalExtent(intervals=[[TEST_DATETIME, None]]) # Pass in a single BBOX @@ -190,7 +194,7 @@ def test_spatial_allows_single_bbox(self): collection.validate() - def test_from_items(self): + def test_from_items(self) -> None: item1 = Item( id="test-item-1", geometry=ARBITRARY_GEOM, diff --git a/tests/test_item.py b/tests/test_item.py index a00a1eca0..3215feeba 100644 --- a/tests/test_item.py +++ b/tests/test_item.py @@ -15,13 +15,13 @@ class ItemTest(unittest.TestCase): - def get_example_item_dict(self): + def get_example_item_dict(self) -> Dict[str, Any]: m = TestCases.get_path("data-files/item/sample-item.json") with open(m) as f: item_dict = json.load(f) return item_dict - def test_to_from_dict(self): + def test_to_from_dict(self) -> None: self.maxDiff = None item_dict = self.get_example_item_dict() @@ -37,7 +37,7 @@ def test_to_from_dict(self): ) self.assertEqual(len(item.assets["thumbnail"].properties), 0) - def test_set_self_href_does_not_break_asset_hrefs(self): + def test_set_self_href_does_not_break_asset_hrefs(self) -> None: cat = TestCases.test_case_2() for item in cat.get_all_items(): for asset in item.assets.values(): @@ -47,7 +47,7 @@ def test_set_self_href_does_not_break_asset_hrefs(self): for asset in item.assets.values(): self.assertTrue(is_absolute_href(asset.href)) - def test_set_self_href_none_ignores_relative_asset_hrefs(self): + def test_set_self_href_none_ignores_relative_asset_hrefs(self) -> None: cat = TestCases.test_case_2() for item in cat.get_all_items(): for asset in item.assets.values(): @@ -57,7 +57,7 @@ def test_set_self_href_none_ignores_relative_asset_hrefs(self): for asset in item.assets.values(): self.assertFalse(is_absolute_href(asset.href)) - def test_asset_absolute_href(self): + def test_asset_absolute_href(self) -> None: item_dict = self.get_example_item_dict() item = Item.from_dict(item_dict) rel_asset = Asset("./data.geojson") @@ -66,7 +66,7 @@ def test_asset_absolute_href(self): actual_href = rel_asset.get_absolute_href() self.assertEqual(expected_href, actual_href) - def test_extra_fields(self): + def test_extra_fields(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item.json") ) @@ -85,7 +85,7 @@ def test_extra_fields(self): self.assertTrue("test" in read_item.extra_fields) self.assertEqual(read_item.extra_fields["test"], "extra") - def test_clearing_collection(self): + def test_clearing_collection(self) -> None: collection = TestCases.test_case_4().get_child("acc") assert isinstance(collection, pystac.Collection) item = next(iter(collection.get_all_items())) @@ -97,7 +97,7 @@ def test_clearing_collection(self): self.assertEqual(item.collection_id, collection.id) self.assertIs(item.get_collection(), collection) - def test_datetime_ISO8601_format(self): + def test_datetime_ISO8601_format(self) -> None: item_dict = self.get_example_item_dict() item = Item.from_dict(item_dict) @@ -106,7 +106,7 @@ def test_datetime_ISO8601_format(self): self.assertEqual("2016-05-03T13:22:30.040000Z", formatted_time) - def test_null_datetime(self): + def test_null_datetime(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item.json") ) @@ -133,7 +133,7 @@ def test_null_datetime(self): null_dt_item.validate() - def test_get_set_asset_datetime(self): + def test_get_set_asset_datetime(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -158,7 +158,7 @@ def test_get_set_asset_datetime(self): str_to_datetime("2018-05-03T13:22:30.040Z"), ) - def test_read_eo_item_owns_asset(self): + def test_read_eo_item_owns_asset(self) -> None: item = next( x for x in TestCases.test_case_1().get_all_items() if isinstance(x, Item) ) @@ -166,7 +166,7 @@ def test_read_eo_item_owns_asset(self): for asset_key in item.assets: self.assertEqual(item.assets[asset_key].owner, item) - def test_null_geometry(self): + def test_null_geometry(self) -> None: m = TestCases.get_path( "data-files/examples/1.0.0-beta.2/item-spec/examples/null-geom-item.json" ) @@ -184,7 +184,7 @@ def test_null_geometry(self): with self.assertRaises(KeyError): item_dict["bbox"] - def test_0_9_item_with_no_extensions_does_not_read_collection_data(self): + def test_0_9_item_with_no_extensions_does_not_read_collection_data(self) -> None: item_json = pystac.StacIO.default().read_json( TestCases.get_path("data-files/examples/hand-0.9.0/010100/010100.json") ) @@ -196,7 +196,7 @@ def test_0_9_item_with_no_extensions_does_not_read_collection_data(self): ) self.assertFalse(did_merge) - def test_clone_sets_asset_owner(self): + def test_clone_sets_asset_owner(self) -> None: cat = TestCases.test_case_2() item = next(iter(cat.get_all_items())) original_asset = list(item.assets.values())[0] @@ -206,7 +206,7 @@ def test_clone_sets_asset_owner(self): clone_asset = list(clone.assets.values())[0] self.assertIs(clone_asset.owner, clone) - def test_make_asset_href_relative_is_noop_on_relative_hrefs(self): + def test_make_asset_href_relative_is_noop_on_relative_hrefs(self) -> None: cat = TestCases.test_case_2() item = next(iter(cat.get_all_items())) asset = list(item.assets.values())[0] @@ -218,7 +218,7 @@ def test_make_asset_href_relative_is_noop_on_relative_hrefs(self): class CommonMetadataTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.URI_1 = TestCases.get_path( "data-files/examples/1.0.0-beta.2/item-spec/examples/datetimerange.json" ) @@ -241,7 +241,7 @@ def setUp(self): ], } - def test_datetimes(self): + def test_datetimes(self) -> None: # save dict of original item to check that `common_metadata` # method doesn't mutate self.item_1 before = self.ITEM_1.clone().to_dict() @@ -254,7 +254,7 @@ def test_datetimes(self): self.assertDictEqual(before, self.ITEM_1.to_dict()) self.assertIsNone(common_metadata.providers) - def test_common_metadata_start_datetime(self): + def test_common_metadata_start_datetime(self) -> None: x = self.ITEM_1.clone() start_datetime_str = "2018-01-01T13:21:30Z" start_datetime_dt = str_to_datetime(start_datetime_str) @@ -269,7 +269,7 @@ def test_common_metadata_start_datetime(self): self.assertEqual(x.common_metadata.start_datetime, example_datetime_dt) self.assertEqual(x.properties["start_datetime"], example_datetime_str) - def test_common_metadata_end_datetime(self): + def test_common_metadata_end_datetime(self) -> None: x = self.ITEM_1.clone() end_datetime_str = "2018-01-01T13:31:30Z" end_datetime_dt = str_to_datetime(end_datetime_str) @@ -284,7 +284,7 @@ def test_common_metadata_end_datetime(self): self.assertEqual(x.common_metadata.end_datetime, example_datetime_dt) self.assertEqual(x.properties["end_datetime"], example_datetime_str) - def test_common_metadata_created(self): + def test_common_metadata_created(self) -> None: x = self.ITEM_2.clone() created_str = "2016-05-04T00:00:01Z" created_dt = str_to_datetime(created_str) @@ -299,7 +299,7 @@ def test_common_metadata_created(self): self.assertEqual(x.common_metadata.created, example_datetime_dt) self.assertEqual(x.properties["created"], example_datetime_str) - def test_common_metadata_updated(self): + def test_common_metadata_updated(self) -> None: x = self.ITEM_2.clone() updated_str = "2017-01-01T00:30:55Z" updated_dt = str_to_datetime(updated_str) @@ -314,7 +314,7 @@ def test_common_metadata_updated(self): self.assertEqual(x.common_metadata.updated, example_datetime_dt) self.assertEqual(x.properties["updated"], example_datetime_str) - def test_common_metadata_providers(self): + def test_common_metadata_providers(self) -> None: x = self.ITEM_2.clone() providers_dict_list: List[Dict[str, Any]] = [ @@ -370,7 +370,7 @@ def test_common_metadata_providers(self): self.assertIsInstance(pd2, dict) self.assertDictEqual(pd1, pd2) - def test_common_metadata_basics(self): + def test_common_metadata_basics(self) -> None: x = self.ITEM_2.clone() # Title @@ -434,7 +434,7 @@ def test_common_metadata_basics(self): self.assertEqual(x.common_metadata.gsd, example_gsd) self.assertEqual(x.properties["gsd"], example_gsd) - def test_asset_start_datetime(self): + def test_asset_start_datetime(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -457,7 +457,7 @@ def test_asset_start_datetime(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.start_datetime, item_value) - def test_asset_end_datetime(self): + def test_asset_end_datetime(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -480,7 +480,7 @@ def test_asset_end_datetime(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.end_datetime, item_value) - def test_asset_license(self): + def test_asset_license(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -503,7 +503,7 @@ def test_asset_license(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.license, item_value) - def test_asset_providers(self): + def test_asset_providers(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -538,7 +538,7 @@ def test_asset_providers(self): self.assertEqual(new_a1_value[0].to_dict(), set_value[0].to_dict()) self.assertEqual(get_opt(cm.providers)[0].to_dict(), item_value[0].to_dict()) - def test_asset_platform(self): + def test_asset_platform(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -561,7 +561,7 @@ def test_asset_platform(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.platform, item_value) - def test_asset_instruments(self): + def test_asset_instruments(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -584,7 +584,7 @@ def test_asset_instruments(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.instruments, item_value) - def test_asset_constellation(self): + def test_asset_constellation(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -607,7 +607,7 @@ def test_asset_constellation(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.constellation, item_value) - def test_asset_mission(self): + def test_asset_mission(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -630,7 +630,7 @@ def test_asset_mission(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.mission, item_value) - def test_asset_gsd(self): + def test_asset_gsd(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -653,7 +653,7 @@ def test_asset_gsd(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.gsd, item_value) - def test_asset_created(self): + def test_asset_created(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) @@ -676,7 +676,7 @@ def test_asset_created(self): self.assertEqual(new_a1_value, set_value) self.assertEqual(cm.created, item_value) - def test_asset_updated(self): + def test_asset_updated(self) -> None: item = pystac.Item.from_file( TestCases.get_path("data-files/item/sample-item-asset-properties.json") ) diff --git a/tests/test_layout.py b/tests/test_layout.py index 3ed7e2815..5158fb580 100644 --- a/tests/test_layout.py +++ b/tests/test_layout.py @@ -16,7 +16,7 @@ class LayoutTemplateTest(unittest.TestCase): - def test_templates_item_datetime(self): + def test_templates_item_datetime(self) -> None: year = 2020 month = 11 day = 3 @@ -45,7 +45,7 @@ def test_templates_item_datetime(self): path = template.substitute(item) self.assertEqual(path, "2020/11/3/2020-11-03/item.json") - def test_templates_item_start_datetime(self): + def test_templates_item_start_datetime(self) -> None: year = 2020 month = 11 day = 3 @@ -77,10 +77,11 @@ def test_templates_item_start_datetime(self): path = template.substitute(item) self.assertEqual(path, "2020/11/3/2020-11-03/item.json") - def test_templates_item_collection(self): + def test_templates_item_collection(self) -> None: template = LayoutTemplate("${collection}/item.json") collection = TestCases.test_case_4().get_child("acc") + assert collection is not None item = next(iter(collection.get_all_items())) assert item.collection_id is not None @@ -92,10 +93,11 @@ def test_templates_item_collection(self): path = template.substitute(item) self.assertEqual(path, "{}/item.json".format(item.collection_id)) - def test_throws_for_no_collection(self): + def test_throws_for_no_collection(self) -> None: template = LayoutTemplate("${collection}/item.json") collection = TestCases.test_case_4().get_child("acc") + assert collection is not None item = next(iter(collection.get_all_items())) item.set_collection(None) assert item.collection_id is None @@ -103,7 +105,7 @@ def test_throws_for_no_collection(self): with self.assertRaises(TemplateError): template.get_template_values(item) - def test_nested_properties(self): + def test_nested_properties(self) -> None: dt = datetime(2020, 11, 3, 18, 30) template = LayoutTemplate("${test.prop}/${ext:extra.test.prop}/item.json") @@ -128,7 +130,7 @@ def test_nested_properties(self): self.assertEqual(path, "4326/3857/item.json") - def test_substitute_with_colon_properties(self): + def test_substitute_with_colon_properties(self) -> None: dt = datetime(2020, 11, 3, 18, 30) template = LayoutTemplate("${ext:prop}/item.json") @@ -145,7 +147,7 @@ def test_substitute_with_colon_properties(self): self.assertEqual(path, "1/item.json") - def test_defaults(self): + def test_defaults(self) -> None: template = LayoutTemplate( "${doesnotexist}/collection.json", defaults={"doesnotexist": "yes"} ) @@ -157,7 +159,7 @@ def test_defaults(self): self.assertEqual(path, "yes/collection.json") - def test_docstring_examples(self): + def test_docstring_examples(self) -> None: item = pystac.Item.from_file( TestCases.get_path( "data-files/examples/1.0.0-beta.2/item-spec/" @@ -183,7 +185,7 @@ def test_docstring_examples(self): class CustomLayoutStrategyTest(unittest.TestCase): def get_custom_catalog_func(self) -> Callable[[pystac.Catalog, str, bool], str]: - def fn(cat: pystac.Catalog, parent_dir: str, is_root: bool): + def fn(cat: pystac.Catalog, parent_dir: str, is_root: bool) -> str: return os.path.join(parent_dir, "cat/{}/{}.json".format(is_root, cat.id)) return fn @@ -191,24 +193,24 @@ def fn(cat: pystac.Catalog, parent_dir: str, is_root: bool): def get_custom_collection_func( self, ) -> Callable[[pystac.Collection, str, bool], str]: - def fn(col: pystac.Collection, parent_dir: str, is_root: bool): + def fn(col: pystac.Collection, parent_dir: str, is_root: bool) -> str: return os.path.join(parent_dir, "col/{}/{}.json".format(is_root, col.id)) return fn def get_custom_item_func(self) -> Callable[[pystac.Item, str], str]: - def fn(item: pystac.Item, parent_dir: str): + def fn(item: pystac.Item, parent_dir: str) -> str: return os.path.join(parent_dir, "item/{}.json".format(item.id)) return fn - def test_produces_layout_for_catalog(self): + def test_produces_layout_for_catalog(self) -> None: strategy = CustomLayoutStrategy(catalog_func=self.get_custom_catalog_func()) cat = pystac.Catalog(id="test", description="test desc") href = strategy.get_href(cat, parent_dir="http://example.com", is_root=True) self.assertEqual(href, "http://example.com/cat/True/test.json") - def test_produces_fallback_layout_for_catalog(self): + def test_produces_fallback_layout_for_catalog(self) -> None: fallback = BestPracticesLayoutStrategy() strategy = CustomLayoutStrategy( collection_func=self.get_custom_collection_func(), @@ -220,7 +222,7 @@ def test_produces_fallback_layout_for_catalog(self): expected = fallback.get_href(cat, parent_dir="http://example.com") self.assertEqual(href, expected) - def test_produces_layout_for_collection(self): + def test_produces_layout_for_collection(self) -> None: strategy = CustomLayoutStrategy( collection_func=self.get_custom_collection_func() ) @@ -230,7 +232,7 @@ def test_produces_layout_for_collection(self): href, "http://example.com/col/False/{}.json".format(collection.id) ) - def test_produces_fallback_layout_for_collection(self): + def test_produces_fallback_layout_for_collection(self) -> None: fallback = BestPracticesLayoutStrategy() strategy = CustomLayoutStrategy( catalog_func=self.get_custom_catalog_func(), @@ -242,14 +244,14 @@ def test_produces_fallback_layout_for_collection(self): expected = fallback.get_href(collection, parent_dir="http://example.com") self.assertEqual(href, expected) - def test_produces_layout_for_item(self): + def test_produces_layout_for_item(self) -> None: strategy = CustomLayoutStrategy(item_func=self.get_custom_item_func()) collection = TestCases.test_case_8() item = next(iter(collection.get_all_items())) href = strategy.get_href(item, parent_dir="http://example.com") self.assertEqual(href, "http://example.com/item/{}.json".format(item.id)) - def test_produces_fallback_layout_for_item(self): + def test_produces_fallback_layout_for_item(self) -> None: fallback = BestPracticesLayoutStrategy() strategy = CustomLayoutStrategy( catalog_func=self.get_custom_catalog_func(), @@ -273,20 +275,20 @@ def _get_collection(self) -> Collection: assert isinstance(result, Collection) return result - def test_produces_layout_for_catalog(self): + def test_produces_layout_for_catalog(self) -> None: strategy = TemplateLayoutStrategy(catalog_template=self.TEST_CATALOG_TEMPLATE) cat = pystac.Catalog(id="test", description="test-desc") href = strategy.get_href(cat, parent_dir="http://example.com") self.assertEqual(href, "http://example.com/cat/test/test-desc/catalog.json") - def test_produces_layout_for_catalog_with_filename(self): + def test_produces_layout_for_catalog_with_filename(self) -> None: template = "cat/${id}/${description}/${id}.json" strategy = TemplateLayoutStrategy(catalog_template=template) cat = pystac.Catalog(id="test", description="test-desc") href = strategy.get_href(cat, parent_dir="http://example.com") self.assertEqual(href, "http://example.com/cat/test/test-desc/test.json") - def test_produces_fallback_layout_for_catalog(self): + def test_produces_fallback_layout_for_catalog(self) -> None: fallback = BestPracticesLayoutStrategy() strategy = TemplateLayoutStrategy( collection_template=self.TEST_COLLECTION_TEMPLATE, @@ -298,7 +300,7 @@ def test_produces_fallback_layout_for_catalog(self): expected = fallback.get_href(cat, parent_dir="http://example.com") self.assertEqual(href, expected) - def test_produces_layout_for_collection(self): + def test_produces_layout_for_collection(self) -> None: strategy = TemplateLayoutStrategy( collection_template=self.TEST_COLLECTION_TEMPLATE ) @@ -311,7 +313,7 @@ def test_produces_layout_for_collection(self): ), ) - def test_produces_layout_for_collection_with_filename(self): + def test_produces_layout_for_collection_with_filename(self) -> None: template = "col/${id}/${license}/col.json" strategy = TemplateLayoutStrategy(collection_template=template) collection = self._get_collection() @@ -323,7 +325,7 @@ def test_produces_layout_for_collection_with_filename(self): ), ) - def test_produces_fallback_layout_for_collection(self): + def test_produces_fallback_layout_for_collection(self) -> None: fallback = BestPracticesLayoutStrategy() strategy = TemplateLayoutStrategy( catalog_template=self.TEST_CATALOG_TEMPLATE, @@ -335,7 +337,7 @@ def test_produces_fallback_layout_for_collection(self): expected = fallback.get_href(collection, parent_dir="http://example.com") self.assertEqual(href, expected) - def test_produces_layout_for_item(self): + def test_produces_layout_for_item(self) -> None: strategy = TemplateLayoutStrategy(item_template=self.TEST_ITEM_TEMPLATE) collection = self._get_collection() item = next(iter(collection.get_all_items())) @@ -345,7 +347,7 @@ def test_produces_layout_for_item(self): "http://example.com/item/{}/{}.json".format(item.collection_id, item.id), ) - def test_produces_layout_for_item_without_filename(self): + def test_produces_layout_for_item_without_filename(self) -> None: template = "item/${collection}" strategy = TemplateLayoutStrategy(item_template=template) collection = self._get_collection() @@ -356,7 +358,7 @@ def test_produces_layout_for_item_without_filename(self): "http://example.com/item/{}/{}.json".format(item.collection_id, item.id), ) - def test_produces_fallback_layout_for_item(self): + def test_produces_fallback_layout_for_item(self) -> None: fallback = BestPracticesLayoutStrategy() strategy = TemplateLayoutStrategy( catalog_template=self.TEST_CATALOG_TEMPLATE, @@ -371,36 +373,36 @@ def test_produces_fallback_layout_for_item(self): class BestPracticesLayoutStrategyTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.strategy = BestPracticesLayoutStrategy() - def test_produces_layout_for_root_catalog(self): + def test_produces_layout_for_root_catalog(self) -> None: cat = pystac.Catalog(id="test", description="test desc") href = self.strategy.get_href( cat, parent_dir="http://example.com", is_root=True ) self.assertEqual(href, "http://example.com/catalog.json") - def test_produces_layout_for_child_catalog(self): + def test_produces_layout_for_child_catalog(self) -> None: cat = pystac.Catalog(id="test", description="test desc") href = self.strategy.get_href(cat, parent_dir="http://example.com") self.assertEqual(href, "http://example.com/test/catalog.json") - def test_produces_layout_for_root_collection(self): + def test_produces_layout_for_root_collection(self) -> None: collection = TestCases.test_case_8() href = self.strategy.get_href( collection, parent_dir="http://example.com", is_root=True ) self.assertEqual(href, "http://example.com/collection.json") - def test_produces_layout_for_child_collection(self): + def test_produces_layout_for_child_collection(self) -> None: collection = TestCases.test_case_8() href = self.strategy.get_href(collection, parent_dir="http://example.com") self.assertEqual( href, "http://example.com/{}/collection.json".format(collection.id) ) - def test_produces_layout_for_item(self): + def test_produces_layout_for_item(self) -> None: collection = TestCases.test_case_8() item = next(iter(collection.get_all_items())) href = self.strategy.get_href(item, parent_dir="http://example.com") diff --git a/tests/test_link.py b/tests/test_link.py index d916f1f07..088f9896e 100644 --- a/tests/test_link.py +++ b/tests/test_link.py @@ -1,5 +1,6 @@ import datetime import unittest +from typing import Any, Dict, List import pystac from tests.utils.test_cases import ARBITRARY_EXTENT @@ -10,7 +11,7 @@ class LinkTest(unittest.TestCase): item: pystac.Item - def setUp(self): + def setUp(self) -> None: self.item = pystac.Item( id="test-item", geometry=None, @@ -19,7 +20,7 @@ def setUp(self): properties={}, ) - def test_minimal(self): + def test_minimal(self) -> None: rel = "my rel" target = "https://example.com/a/b" link = pystac.Link(rel, target) @@ -53,7 +54,7 @@ def test_minimal(self): link.set_owner(self.item) self.assertEqual(self.item, link.owner) - def test_relative(self): + def test_relative(self) -> None: rel = "my rel" target = "../elsewhere" mime_type = "example/stac_thing" @@ -67,27 +68,28 @@ def test_relative(self): } self.assertEqual(expected_dict, link.to_dict()) - def test_link_does_not_fail_if_href_is_none(self): + def test_link_does_not_fail_if_href_is_none(self) -> None: """Test to ensure get_href does not fail when the href is None.""" catalog = pystac.Catalog(id="test", description="test desc") catalog.add_item(self.item) catalog.set_self_href("/some/href") link = catalog.get_single_link("item") + assert link is not None self.assertIsNone(link.get_href()) - def test_resolve_stac_object_no_root_and_target_is_item(self): + def test_resolve_stac_object_no_root_and_target_is_item(self) -> None: link = pystac.Link("my rel", target=self.item) link.resolve_stac_object() class StaticLinkTest(unittest.TestCase): - def test_from_dict_round_trip(self): - test_cases = [ + def test_from_dict_round_trip(self) -> None: + test_cases: List[Dict[str, Any]] = [ {"rel": "", "href": ""}, # Not valid, but works. {"rel": "r", "href": "t"}, {"rel": "r", "href": "/t"}, - {"rel": "r", "href": "t", "type": "a/b", "title": "t", "c": "d", 1: 2}, + {"rel": "r", "href": "t", "type": "a/b", "title": "t", "c": "d", "1": 2}, # Special case. {"rel": "self", "href": "t"}, ] @@ -95,18 +97,19 @@ def test_from_dict_round_trip(self): d2 = pystac.Link.from_dict(d).to_dict() self.assertEqual(d, d2) - def test_from_dict_failures(self): - for d in [{}, {"href": "t"}, {"rel": "r"}]: + def test_from_dict_failures(self) -> None: + dicts: List[Dict[str, Any]] = [{}, {"href": "t"}, {"rel": "r"}] + for d in dicts: with self.assertRaises(KeyError): pystac.Link.from_dict(d) - def test_collection(self): + def test_collection(self) -> None: c = pystac.Collection("collection id", "desc", extent=ARBITRARY_EXTENT) link = pystac.Link.collection(c) expected = {"rel": "collection", "href": None, "type": "application/json"} self.assertEqual(expected, link.to_dict()) - def test_child(self): + def test_child(self) -> None: c = pystac.Collection("collection id", "desc", extent=ARBITRARY_EXTENT) link = pystac.Link.child(c) expected = {"rel": "child", "href": None, "type": "application/json"} diff --git a/tests/test_stac_io.py b/tests/test_stac_io.py index 97b18649c..58ac51e23 100644 --- a/tests/test_stac_io.py +++ b/tests/test_stac_io.py @@ -7,7 +7,7 @@ class StacIOTest(unittest.TestCase): - def test_stac_io_issues_warnings(self): + def test_stac_io_issues_warnings(self) -> None: with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") @@ -20,7 +20,7 @@ def test_stac_io_issues_warnings(self): self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) - def test_read_text(self): + def test_read_text(self) -> None: _ = pystac.read_file( TestCases.get_path("data-files/collections/multi-extent.json") ) diff --git a/tests/test_utils.py b/tests/test_utils.py index 639df2a35..d813f225e 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -10,7 +10,7 @@ class UtilsTest(unittest.TestCase): - def test_make_relative_href(self): + def test_make_relative_href(self) -> None: # Test cases of (source_href, start_href, expected) test_cases = [ ("/a/b/c/d/catalog.json", "/a/b/c/catalog.json", "./d/catalog.json"), @@ -47,7 +47,7 @@ def test_make_relative_href(self): actual = make_relative_href(source_href, start_href) self.assertEqual(actual, expected) - def test_make_relative_href_windows(self): + def test_make_relative_href_windows(self) -> None: utils._pathlib = ntpath try: # Test cases of (source_href, start_href, expected) @@ -102,7 +102,7 @@ def test_make_relative_href_windows(self): finally: utils._pathlib = os.path - def test_make_absolute_href(self): + def test_make_absolute_href(self) -> None: # Test cases of (source_href, start_href, expected) test_cases = [ ("item.json", "/a/b/c/catalog.json", "/a/b/c/item.json"), @@ -135,14 +135,14 @@ def test_make_absolute_href(self): actual = make_absolute_href(source_href, start_href) self.assertEqual(actual, expected) - def test_make_absolute_href_on_vsitar(self): + def test_make_absolute_href_on_vsitar(self) -> None: rel_path = "some/item.json" cat_path = "/vsitar//tmp/catalog.tar/catalog.json" expected = "/vsitar//tmp/catalog.tar/some/item.json" self.assertEqual(expected, make_absolute_href(rel_path, cat_path)) - def test_make_absolute_href_windows(self): + def test_make_absolute_href_windows(self) -> None: utils._pathlib = ntpath try: # Test cases of (source_href, start_href, expected) @@ -183,7 +183,7 @@ def test_make_absolute_href_windows(self): finally: utils._pathlib = os.path - def test_is_absolute_href(self): + def test_is_absolute_href(self) -> None: # Test cases of (href, expected) test_cases = [ ("item.json", False), @@ -197,7 +197,7 @@ def test_is_absolute_href(self): actual = is_absolute_href(href) self.assertEqual(actual, expected) - def test_is_absolute_href_windows(self): + def test_is_absolute_href_windows(self) -> None: utils._pathlib = ntpath try: @@ -216,7 +216,7 @@ def test_is_absolute_href_windows(self): finally: utils._pathlib = os.path - def test_datetime_to_str(self): + def test_datetime_to_str(self) -> None: cases = ( ( "timezone naive, assume utc", @@ -240,7 +240,7 @@ def test_datetime_to_str(self): got = utils.datetime_to_str(dt) self.assertEqual(expected, got) - def test_geojson_bbox(self): + def test_geojson_bbox(self) -> None: # Use sample Geojson from https://en.wikipedia.org/wiki/GeoJSON with open("tests/data-files/geojson/sample.geojson") as sample_geojson: all_features = json.load(sample_geojson) diff --git a/tests/test_version.py b/tests/test_version.py index cc48ff1b7..3c20ee852 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -6,18 +6,18 @@ class VersionTest(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self._prev_env_version = os.environ.get("PYSTAC_STAC_VERSION_OVERRIDE") self._prev_version = pystac.get_stac_version() - def tearDown(self): + def tearDown(self) -> None: if self._prev_env_version is None: os.environ.pop("PYSTAC_STAC_VERSION_OVERRIDE", None) else: os.environ["PYSTAC_STAC_VERSION_OVERRIDE"] = self._prev_env_version pystac.set_stac_version(None) - def test_override_stac_version_with_environ(self): + def test_override_stac_version_with_environ(self) -> None: override_version = "1.0.0-gamma.2" os.environ["PYSTAC_STAC_VERSION_OVERRIDE"] = override_version @@ -25,7 +25,7 @@ def test_override_stac_version_with_environ(self): d = cat.to_dict() self.assertEqual(d["stac_version"], override_version) - def test_override_stac_version_with_call(self): + def test_override_stac_version_with_call(self) -> None: override_version = "1.0.0-delta.2" pystac.set_stac_version(override_version) cat = TestCases.test_case_1() diff --git a/tests/test_writing.py b/tests/test_writing.py index 508896280..4bbe2e3b8 100644 --- a/tests/test_writing.py +++ b/tests/test_writing.py @@ -1,5 +1,6 @@ import unittest from tempfile import TemporaryDirectory +from typing import Any, List import pystac from pystac import Collection, CatalogType, HIERARCHICAL_LINKS @@ -14,7 +15,7 @@ class STACWritingTest(unittest.TestCase): and ensure that links are correctly set to relative or absolute. """ - def validate_catalog(self, catalog: pystac.Catalog): + def validate_catalog(self, catalog: pystac.Catalog) -> int: catalog.validate() validated_count = 1 @@ -27,12 +28,14 @@ def validate_catalog(self, catalog: pystac.Catalog): return validated_count - def validate_file(self, path: str, object_type: str): + def validate_file(self, path: str, object_type: str) -> List[Any]: d = pystac.StacIO.default().read_json(path) return validate_dict(d, pystac.STACObjectType(object_type)) - def validate_link_types(self, root_href: str, catalog_type: pystac.CatalogType): - def validate_asset_href_type(item: pystac.Item, item_href: str): + def validate_link_types( + self, root_href: str, catalog_type: pystac.CatalogType + ) -> None: + def validate_asset_href_type(item: pystac.Item, item_href: str) -> None: for asset in item.assets.values(): if not is_absolute_href(asset.href): is_valid = not is_absolute_href(asset.href) @@ -46,7 +49,7 @@ def validate_asset_href_type(item: pystac.Item, item_href: str): def validate_item_link_type( href: str, link_type: str, should_include_self: bool - ): + ) -> None: item_dict = pystac.StacIO.default().read_json(href) item = pystac.Item.from_file(href) rel_links = ( @@ -67,7 +70,7 @@ def validate_item_link_type( def validate_catalog_link_type( href: str, link_type: str, should_include_self: bool - ): + ) -> None: cat_dict = pystac.StacIO.default().read_json(href) cat = pystac.Catalog.from_file(href) @@ -99,7 +102,9 @@ def validate_catalog_link_type( validate_catalog_link_type(root_href, link_type, root_should_include_href) - def do_test(self, catalog: pystac.Catalog, catalog_type: pystac.CatalogType): + def do_test( + self, catalog: pystac.Catalog, catalog_type: pystac.CatalogType + ) -> None: with TemporaryDirectory() as tmp_dir: catalog.normalize_hrefs(tmp_dir) self.validate_catalog(catalog) @@ -119,7 +124,7 @@ def do_test(self, catalog: pystac.Catalog, catalog_type: pystac.CatalogType): for item in items: self.validate_file(item.self_href, pystac.STACObjectType.ITEM) - def test_testcases(self): + def test_testcases(self) -> None: for catalog in TestCases.all_test_catalogs(): catalog = catalog.full_copy() ctypes = [ diff --git a/tests/utils/stac_io_mock.py b/tests/utils/stac_io_mock.py index 57904df5c..1ff0d437d 100644 --- a/tests/utils/stac_io_mock.py +++ b/tests/utils/stac_io_mock.py @@ -9,7 +9,7 @@ class MockStacIO(pystac.StacIO): clients to replace STAC_IO functionality, all within a context scope. """ - def __init__(self): + def __init__(self) -> None: self.mock = Mock() def read_text( diff --git a/tests/utils/test_cases.py b/tests/utils/test_cases.py index 4faae0f6c..4fc820265 100644 --- a/tests/utils/test_cases.py +++ b/tests/utils/test_cases.py @@ -203,7 +203,7 @@ def test_case_3() -> Catalog: return root_cat @staticmethod - def test_case_4(): + def test_case_4() -> Catalog: """Test case that is based on a local copy of the Tier 1 dataset from DrivenData's OpenCities AI Challenge. See: https://www.drivendata.org/competitions/60/building-segmentation-disaster-resilience @@ -213,21 +213,21 @@ def test_case_4(): ) @staticmethod - def test_case_5(): + def test_case_5() -> Catalog: """Based on a subset of https://cbers.stac.cloud/""" return Catalog.from_file( TestCases.get_path("data-files/catalogs/test-case-5/catalog.json") ) @staticmethod - def test_case_6(): + def test_case_6() -> Catalog: """Based on a subset of CBERS, contains a root and 4 empty children""" return Catalog.from_file( TestCases.get_path("data-files/catalogs/cbers-partial/catalog.json") ) @staticmethod - def test_case_7(): + def test_case_7() -> Catalog: """Test case 4 as STAC version 0.8.1""" return Catalog.from_file( TestCases.get_path("data-files/catalogs/label_catalog-v0.8.1/catalog.json") diff --git a/tests/validation/test_schema_uri_map.py b/tests/validation/test_schema_uri_map.py index dd6954a7a..9075710dc 100644 --- a/tests/validation/test_schema_uri_map.py +++ b/tests/validation/test_schema_uri_map.py @@ -5,7 +5,7 @@ class SchemaUriMapTest(unittest.TestCase): - def test_gets_schema_uri_for_old_version(self): + def test_gets_schema_uri_for_old_version(self) -> None: d = DefaultSchemaUriMap() uri = d.get_object_schema_uri(pystac.STACObjectType.ITEM, "0.8.0") diff --git a/tests/validation/test_validate.py b/tests/validation/test_validate.py index 12b8d33cb..6c2dae259 100644 --- a/tests/validation/test_validate.py +++ b/tests/validation/test_validate.py @@ -17,7 +17,7 @@ class ValidateTest(unittest.TestCase): - def test_validate_current_version(self): + def test_validate_current_version(self) -> None: catalog = pystac.read_file( TestCases.get_path("data-files/catalogs/test-case-1/" "catalog.json") ) @@ -35,7 +35,7 @@ def test_validate_current_version(self): item = pystac.read_file(TestCases.get_path("data-files/item/sample-item.json")) item.validate() - def test_validate_examples(self): + def test_validate_examples(self) -> None: for example in TestCases.get_examples_info(): with self.subTest(example.path): stac_version = example.stac_version @@ -72,10 +72,11 @@ def test_validate_examples(self): ) raise e - def test_validate_error_contains_href(self): + def test_validate_error_contains_href(self) -> None: # Test that the exception message contains the HREF of the object if available. cat = TestCases.test_case_1() item = cat.get_item("area-1-1-labels", recursive=True) + assert item is not None assert item.get_self_href() is not None item.geometry = {"type": "INVALID"} @@ -87,7 +88,7 @@ def test_validate_error_contains_href(self): self.assertTrue(get_opt(item.get_self_href()) in str(e)) raise e - def test_validate_all(self): + def test_validate_all(self) -> None: for test_case in TestCases.all_test_catalogs(): catalog_href = test_case.get_self_href() if catalog_href is not None: @@ -124,7 +125,7 @@ def test_validate_all(self): with self.assertRaises(pystac.STACValidationError): pystac.validation.validate_all(stac_dict, new_cat_href) - def test_validates_geojson_with_tuple_coordinates(self): + def test_validates_geojson_with_tuple_coordinates(self) -> None: """This unit tests guards against a bug where if a geometry dict has tuples instead of lists for the coordinate sequence, which can be produced by shapely, then the geometry still passses