class TestCoreSearchResults(unittest.TestCase): def setUp(self): self.dag = EODataAccessGateway() self.maxDiff = None self.geojson_repr = { "features": [{ "properties": { "snowCover": None, "resolution": None, "completionTimeFromAscendingNode": "2018-02-16T00:12:14.035Z", "keyword": {}, "productType": "OCN", "downloadLink": ("https://peps.cnes.fr/resto/collections/S1/" "578f1768-e66e-5b86-9363-b19f8931cc7b/download"), "eodag_provider": "peps", "eodag_product_type": "S1_OCN", "platformSerialIdentifier": "S1A", "cloudCover": 0, "title": "S1A_WV_OCN__2SSV_20180215T235323_" "20180216T001213_020624_023501_0FD3", "orbitNumber": 20624, "instrument": "SAR-C SAR", "abstract": None, "eodag_search_intersection": { "coordinates": [[ [89.590721, 2.614019], [89.771805, 2.575546], [89.809341, 2.756323], [89.628258, 2.794767], [89.590721, 2.614019], ]], "type": "Polygon", }, "organisationName": None, "startTimeFromAscendingNode": "2018-02-15T23:53:22.871Z", "platform": None, "sensorType": None, "processingLevel": None, "orbitType": None, "topicCategory": None, "orbitDirection": None, "parentIdentifier": None, "sensorMode": None, "quicklook": None, }, "id": "578f1768-e66e-5b86-9363-b19f8931cc7b", "type": "Feature", "geometry": { "coordinates": [[ [89.590721, 2.614019], [89.771805, 2.575546], [89.809341, 2.756323], [89.628258, 2.794767], [89.590721, 2.614019], ]], "type": "Polygon", }, }], "type": "FeatureCollection", } self.search_result = SearchResult.from_geojson(self.geojson_repr) # Ensure that each product in a search result has geometry and search # intersection as a shapely geometry for product in self.search_result: product.search_intersection = geometry.shape( product.search_intersection) def test_core_serialize_search_results(self): """The core api must serialize a search results to geojson""" with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: # Serialization when the destination file is specified => goes to the # specified file path = self.dag.serialize(self.search_result, filename=f.name) self.assertEqual(path, f.name) with open(path, "r") as f: self.make_assertions(f) os.unlink(path) # Serialization when the destination is not specified => goes to # 'search_results.geojson' in the cur dir tmpdirname = tempfile.mkdtemp() current_dir = os.getcwd() os.chdir(tmpdirname) self.assertEqual(self.dag.serialize(self.search_result), "search_results.geojson") os.chdir(current_dir) shutil.rmtree(tmpdirname) def test_core_deserialize_search_results(self): """The core api must deserialize a search result from geojson""" search_results_geojson_path = os.path.join( TEST_RESOURCES_PATH, "eodag_search_result.geojson") search_result = self.dag.deserialize(search_results_geojson_path) self.assertIsInstance(search_result, SearchResult) with open(search_results_geojson_path, "r") as f: self.make_assertions(f) def make_assertions(self, f): d = json.load(f) self.assertEqual(d["type"], self.geojson_repr["type"]) self.assertEqual(len(d["features"]), len(self.geojson_repr["features"])) feature = d["features"][0] self.assertEqual(feature["id"], self.geojson_repr["features"][0]["id"]) self.assertEqual(feature["type"], self.geojson_repr["features"][0]["type"]) self.assertDictEqual(feature["geometry"], self.geojson_repr["features"][0]["geometry"]) for key, value in self.geojson_repr["features"][0]["properties"].items( ): if key not in ("geometry", "id"): if isinstance(value, dict): self.assertDictEqual(value, feature["properties"][key]) elif isinstance(value, list): self.assertListEqual(value, feature["properties"][key]) else: self.assertEqual(value, feature["properties"][key]) else: self.assertEqual(value, feature[key])
class TestCoreSearchResults(unittest.TestCase): def setUp(self): self.dag = EODataAccessGateway() self.maxDiff = None self.geojson_repr = { "features": [ { "properties": { "snowCover": None, "resolution": None, "completionTimeFromAscendingNode": "2018-02-16T00:12:14.035Z", "keyword": {}, "productType": "OCN", "downloadLink": ( "https://peps.cnes.fr/resto/collections/S1/" "578f1768-e66e-5b86-9363-b19f8931cc7b/download" ), "eodag_provider": "peps", "eodag_product_type": "S1_SAR_OCN", "platformSerialIdentifier": "S1A", "cloudCover": 0, "title": "S1A_WV_OCN__2SSV_20180215T235323_" "20180216T001213_020624_023501_0FD3", "orbitNumber": 20624, "instrument": "SAR-C SAR", "abstract": None, "eodag_search_intersection": { "coordinates": [ [ [89.590721, 2.614019], [89.771805, 2.575546], [89.809341, 2.756323], [89.628258, 2.794767], [89.590721, 2.614019], ] ], "type": "Polygon", }, "organisationName": None, "startTimeFromAscendingNode": "2018-02-15T23:53:22.871Z", "platform": None, "sensorType": None, "processingLevel": None, "orbitType": None, "topicCategory": None, "orbitDirection": None, "parentIdentifier": None, "sensorMode": None, "quicklook": None, }, "id": "578f1768-e66e-5b86-9363-b19f8931cc7b", "type": "Feature", "geometry": { "coordinates": [ [ [89.590721, 2.614019], [89.771805, 2.575546], [89.809341, 2.756323], [89.628258, 2.794767], [89.590721, 2.614019], ] ], "type": "Polygon", }, } ], "type": "FeatureCollection", } self.search_result = SearchResult.from_geojson(self.geojson_repr) # Ensure that each product in a search result has geometry and search # intersection as a shapely geometry for product in self.search_result: product.search_intersection = geometry.shape(product.search_intersection) def test_core_serialize_search_results(self): """The core api must serialize a search results to geojson""" with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: # Serialization when the destination file is specified => goes to the # specified file path = self.dag.serialize(self.search_result, filename=f.name) self.assertEqual(path, f.name) with open(path, "r") as f: self.make_assertions(f) os.unlink(path) # Serialization when the destination is not specified => goes to # 'search_results.geojson' in the cur dir tmpdirname = tempfile.mkdtemp() current_dir = os.getcwd() os.chdir(tmpdirname) self.assertEqual( self.dag.serialize(self.search_result), "search_results.geojson" ) os.chdir(current_dir) shutil.rmtree(tmpdirname) def test_core_deserialize_search_results(self): """The core api must deserialize a search result from geojson""" search_results_geojson_path = os.path.join( TEST_RESOURCES_PATH, "eodag_search_result.geojson" ) search_result = self.dag.deserialize(search_results_geojson_path) self.assertIsInstance(search_result, SearchResult) with open(search_results_geojson_path, "r") as f: self.make_assertions(f) def make_assertions(self, f): d = json.load(f) self.assertEqual(d["type"], self.geojson_repr["type"]) self.assertEqual(len(d["features"]), len(self.geojson_repr["features"])) feature = d["features"][0] self.assertEqual(feature["id"], self.geojson_repr["features"][0]["id"]) self.assertEqual(feature["type"], self.geojson_repr["features"][0]["type"]) self.assertDictEqual( feature["geometry"], self.geojson_repr["features"][0]["geometry"] ) for key, value in self.geojson_repr["features"][0]["properties"].items(): if key not in ("geometry", "id"): if isinstance(value, dict): self.assertDictEqual(value, feature["properties"][key]) elif isinstance(value, list): self.assertListEqual(value, feature["properties"][key]) else: self.assertEqual(value, feature["properties"][key]) else: self.assertEqual(value, feature[key]) @staticmethod def _minimal_eoproduct_geojson_repr(eo_id, geom_coords, geom_type="Polygon"): return { "properties": { "eodag_provider": "peps", "eodag_product_type": "S1_SAR_OCN", "eodag_search_intersection": { "coordinates": geom_coords, "type": geom_type, }, }, "id": eo_id, "geometry": {"coordinates": geom_coords, "type": geom_type}, } def test_group_by_extent(self): geom_coords_1 = [[[89, 2], [90, 2], [90, 3], [89, 3], [89, 2]]] geom_coords_2 = [[[90, 3], [91, 3], [91, 4], [90, 4], [90, 3]]] geom_coords_3 = [[[92, 4], [92, 4], [92, 5], [91, 5], [91, 4]]] eo_geom1 = EOProduct.from_geojson( self._minimal_eoproduct_geojson_repr("1", geom_coords_1) ) eo_geom2 = EOProduct.from_geojson( self._minimal_eoproduct_geojson_repr("2", geom_coords_2) ) eo_geom3 = EOProduct.from_geojson( self._minimal_eoproduct_geojson_repr("3", geom_coords_3) ) first_search = SearchResult([eo_geom1]) second_search = SearchResult([eo_geom1, eo_geom2]) third_search = SearchResult([eo_geom1, eo_geom2, eo_geom3]) grouped_searches = EODataAccessGateway.group_by_extent( [first_search, second_search, third_search] ) # The returned value is a List[SearchResult] self.assertIsInstance(grouped_searches, list) self.assertTrue(all(isinstance(sr, SearchResult) for sr in grouped_searches)) # We expect three groups because we have given products that have # three different geometry bounds. self.assertEqual(len(grouped_searches), 3) # Given how the search results were constructed the resulting groups # must have these 3 different lengths. ss_len = [len(sr) for sr in grouped_searches] self.assertIn(1, ss_len) self.assertIn(2, ss_len) self.assertIn(3, ss_len)