From b169493e087891b72fe6c0b39b36fcf0f08b3f41 Mon Sep 17 00:00:00 2001 From: Reifenrath Date: Wed, 28 Aug 2024 14:10:46 +0200 Subject: [PATCH 1/5] deleted all traces of report --- ohsome_quality_api/api/api.py | 64 +--------- ohsome_quality_api/api/response_models.py | 14 --- ohsome_quality_api/definitions.py | 8 +- ohsome_quality_api/oqt.py | 49 +------- ohsome_quality_api/reports/__init__.py | 0 ohsome_quality_api/reports/base.py | 117 ------------------ .../reports/building_report/__init__.py | 0 .../reports/building_report/metadata.yaml | 20 --- .../reports/building_report/report.py | 25 ---- ohsome_quality_api/reports/definitions.py | 20 --- .../reports/food_related_report/__init__.py | 0 .../reports/food_related_report/metadata.yaml | 21 ---- .../reports/food_related_report/report.py | 43 ------- .../reports/map_action_poc/__init__.py | 0 .../reports/map_action_poc/metadata.yaml | 21 ---- .../reports/map_action_poc/report.py | 32 ----- .../reports/minimal/__init__.py | 0 .../reports/minimal/metadata.yaml | 24 ---- ohsome_quality_api/reports/minimal/report.py | 29 ----- ohsome_quality_api/reports/models.py | 39 ------ .../multilevel_currentness/__init__.py | 0 .../multilevel_currentness/metadata.yaml | 18 --- .../reports/multilevel_currentness/report.py | 31 ----- .../multilevel_mapping_saturation/__init__.py | 0 .../metadata.yaml | 16 --- .../multilevel_mapping_saturation/report.py | 31 ----- .../remote_mapping_level_one/__init__.py | 0 .../remote_mapping_level_one/report.py | 23 ---- .../reports/road_report/__init__.py | 0 .../reports/road_report/metadata.yaml | 19 --- .../reports/road_report/report.py | 30 ----- .../reports/sketchmap_fitness/__init__.py | 0 .../reports/sketchmap_fitness/metadata.yaml | 26 ---- .../reports/sketchmap_fitness/report.py | 26 ---- tests/conftest.py | 11 -- .../api/test_metadata_reports.py | 64 ---------- tests/integrationtests/test_base_report.py | 100 --------------- tests/unittests/api/test_response_models.py | 24 ---- tests/unittests/test_definitions.py | 15 --- tests/unittests/test_helper.py | 6 - .../unittests/test_report_building_report.py | 30 ----- .../test_report_food_related_report.py | 30 ----- tests/unittests/test_report_map_action_poc.py | 29 ----- tests/unittests/test_report_minimal.py | 29 ----- .../test_report_multilevel_currentness.py | 32 ----- ...st_report_multilevel_mapping_saturation.py | 32 ----- tests/unittests/test_report_road_report.py | 30 ----- .../test_report_sketchmap_fitness.py | 29 ----- tests/unittests/test_reports_definitions.py | 21 ---- 49 files changed, 5 insertions(+), 1223 deletions(-) delete mode 100644 ohsome_quality_api/reports/__init__.py delete mode 100644 ohsome_quality_api/reports/base.py delete mode 100644 ohsome_quality_api/reports/building_report/__init__.py delete mode 100644 ohsome_quality_api/reports/building_report/metadata.yaml delete mode 100644 ohsome_quality_api/reports/building_report/report.py delete mode 100644 ohsome_quality_api/reports/definitions.py delete mode 100644 ohsome_quality_api/reports/food_related_report/__init__.py delete mode 100644 ohsome_quality_api/reports/food_related_report/metadata.yaml delete mode 100644 ohsome_quality_api/reports/food_related_report/report.py delete mode 100644 ohsome_quality_api/reports/map_action_poc/__init__.py delete mode 100644 ohsome_quality_api/reports/map_action_poc/metadata.yaml delete mode 100644 ohsome_quality_api/reports/map_action_poc/report.py delete mode 100644 ohsome_quality_api/reports/minimal/__init__.py delete mode 100644 ohsome_quality_api/reports/minimal/metadata.yaml delete mode 100644 ohsome_quality_api/reports/minimal/report.py delete mode 100644 ohsome_quality_api/reports/models.py delete mode 100644 ohsome_quality_api/reports/multilevel_currentness/__init__.py delete mode 100644 ohsome_quality_api/reports/multilevel_currentness/metadata.yaml delete mode 100644 ohsome_quality_api/reports/multilevel_currentness/report.py delete mode 100644 ohsome_quality_api/reports/multilevel_mapping_saturation/__init__.py delete mode 100644 ohsome_quality_api/reports/multilevel_mapping_saturation/metadata.yaml delete mode 100644 ohsome_quality_api/reports/multilevel_mapping_saturation/report.py delete mode 100644 ohsome_quality_api/reports/remote_mapping_level_one/__init__.py delete mode 100644 ohsome_quality_api/reports/remote_mapping_level_one/report.py delete mode 100644 ohsome_quality_api/reports/road_report/__init__.py delete mode 100644 ohsome_quality_api/reports/road_report/metadata.yaml delete mode 100644 ohsome_quality_api/reports/road_report/report.py delete mode 100644 ohsome_quality_api/reports/sketchmap_fitness/__init__.py delete mode 100644 ohsome_quality_api/reports/sketchmap_fitness/metadata.yaml delete mode 100644 ohsome_quality_api/reports/sketchmap_fitness/report.py delete mode 100644 tests/integrationtests/api/test_metadata_reports.py delete mode 100644 tests/integrationtests/test_base_report.py delete mode 100644 tests/unittests/test_report_building_report.py delete mode 100644 tests/unittests/test_report_food_related_report.py delete mode 100644 tests/unittests/test_report_map_action_poc.py delete mode 100644 tests/unittests/test_report_minimal.py delete mode 100644 tests/unittests/test_report_multilevel_currentness.py delete mode 100644 tests/unittests/test_report_multilevel_mapping_saturation.py delete mode 100644 tests/unittests/test_report_road_report.py delete mode 100644 tests/unittests/test_report_sketchmap_fitness.py delete mode 100644 tests/unittests/test_reports_definitions.py diff --git a/ohsome_quality_api/api/api.py b/ohsome_quality_api/api/api.py index 4b61a06df..a0a710d68 100644 --- a/ohsome_quality_api/api/api.py +++ b/ohsome_quality_api/api/api.py @@ -1,9 +1,9 @@ import json import logging import os -from typing import Annotated, Any, Union +from typing import Any, Union -from fastapi import FastAPI, HTTPException, Path, Request, status +from fastapi import FastAPI, HTTPException, Request, status from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware @@ -28,7 +28,6 @@ AttributeCompletenessRequest, IndicatorDataRequest, IndicatorRequest, - ReportRequest, ) from ohsome_quality_api.api.response_models import ( AttributeMetadataResponse, @@ -39,7 +38,6 @@ MetadataResponse, ProjectMetadataResponse, QualityDimensionMetadataResponse, - ReportMetadataResponse, TopicMetadataResponse, ) from ohsome_quality_api.attributes.definitions import get_attributes, load_attributes @@ -64,10 +62,6 @@ get_quality_dimension, get_quality_dimensions, ) -from ohsome_quality_api.reports.definitions import ( - ReportEnum, - get_report_metadata, -) from ohsome_quality_api.topics.definitions import ( TopicEnum, get_topic_preset, @@ -354,27 +348,6 @@ async def _post_indicator( ) -@app.post("/reports/{key}", include_in_schema=False) -async def post_report( - key: Annotated[ - ReportEnum, - Path( - title="Report Key", - example="building-report", - ), - ], - parameters: ReportRequest, -) -> CustomJSONResponse: - geojson_object = await oqt.create_report(parameters, key=key.value) - response = empty_api_response() - response["attribution"]["text"] = get_class_from_key( - class_type="report", - key=key.value, - ).attribution() - response.update(geojson_object) - return CustomJSONResponse(content=response, media_type=MEDIA_TYPE_GEOJSON) - - @app.get("/metadata", tags=["metadata"], response_model=MetadataResponse) async def metadata(project: ProjectEnum = DEFAULT_PROJECT) -> Any: """All metadata.""" @@ -386,7 +359,6 @@ async def metadata(project: ProjectEnum = DEFAULT_PROJECT) -> Any: "quality_dimensions": get_quality_dimensions(), "projects": get_project_metadata(), "indicators": get_indicator_metadata(project=project), - # "reports": get_report_metadata(project=project), "attributes": get_attributes(), } } @@ -493,35 +465,3 @@ async def metadata_indicators_coverage( ) -> Any: """Get coverage geometry of an indicator by key.""" return await get_coverage(key.value, inverse) - - -@app.get( - "/metadata/reports", - tags=["metadata"], - response_model_exclude={ - "result": {k.value: {"label_description": True} for k in ReportEnum} - }, - include_in_schema=False, -) -async def metadata_reports( - project: ProjectEnum = DEFAULT_PROJECT, -) -> ReportMetadataResponse: - """Get metadata of all indicators.""" - if project == ProjectEnum.all: - project = None - return ReportMetadataResponse(result=get_report_metadata(project=project)) - - -@app.get( - "/metadata/reports/{key}", - tags=["metadata"], - response_model_exclude={ - "result": {k.value: {"label_description": True} for k in ReportEnum} - }, - include_in_schema=False, -) -async def metadata_reports_by_key(key: ReportEnum) -> ReportMetadataResponse: - """Get metadata of an indicator by key.""" - return ReportMetadataResponse( - result={key.value: get_metadata("reports", hyphen_to_camel(key.value))} - ) diff --git a/ohsome_quality_api/api/response_models.py b/ohsome_quality_api/api/response_models.py index 48ffb2322..7b626c684 100644 --- a/ohsome_quality_api/api/response_models.py +++ b/ohsome_quality_api/api/response_models.py @@ -11,8 +11,6 @@ from ohsome_quality_api.projects.models import Project from ohsome_quality_api.quality_dimensions.definitions import QualityDimensionEnum from ohsome_quality_api.quality_dimensions.models import QualityDimension -from ohsome_quality_api.reports.definitions import ReportEnum -from ohsome_quality_api.reports.models import ReportMetadata from ohsome_quality_api.topics.definitions import TopicEnum from ohsome_quality_api.utils.helper import snake_to_lower_camel @@ -123,18 +121,6 @@ class IndicatorMetadataCoverageResponse( model_config = ConfigDict(title="Indicator Coverage", extra="allow") -class ReportMetadataResponse(BaseResponse): - result: dict[str, ReportMetadata] - - @field_validator("result") - @classmethod - def check_report_dict(cls, value): - assert len(value) > 0 - for key in value.keys(): - ReportEnum(key) - return value - - class Metadata(BaseConfig): indicators: dict[str, IndicatorMetadata] topics: dict[str, TopicMetadata] diff --git a/ohsome_quality_api/definitions.py b/ohsome_quality_api/definitions.py index 591d5ccba..9191f60a2 100644 --- a/ohsome_quality_api/definitions.py +++ b/ohsome_quality_api/definitions.py @@ -9,7 +9,6 @@ import yaml from ohsome_quality_api.indicators.models import IndicatorMetadata -from ohsome_quality_api.reports.models import ReportMetadata from ohsome_quality_api.topics.definitions import load_topic_presets from ohsome_quality_api.utils.helper import ( camel_to_hyphen, @@ -52,7 +51,7 @@ class Color(Enum): def load_metadata( module_name: Literal["indicators", "reports"], -) -> dict[str, IndicatorMetadata | ReportMetadata]: +) -> dict[str, IndicatorMetadata]: """Read metadata of all indicators or reports from YAML files. Those text files are located in the directory of each indicator/report. @@ -75,15 +74,12 @@ def load_metadata( case "indicators": for k, v in raw.items(): metadata[k] = IndicatorMetadata(**v) - case "reports": - for k, v in raw.items(): - metadata[k] = ReportMetadata(**v) return metadata def get_metadata( module_name: Literal["indicators", "reports"], class_name: str -) -> IndicatorMetadata | ReportMetadata: +) -> IndicatorMetadata: """Get metadata of an indicator or report based on its class name. This is implemented outside the metadata class to be able to access metadata of all diff --git a/ohsome_quality_api/oqt.py b/ohsome_quality_api/oqt.py index 2b09a8598..35016c260 100644 --- a/ohsome_quality_api/oqt.py +++ b/ohsome_quality_api/oqt.py @@ -1,16 +1,11 @@ -"""Controller for computing Indicators and Reports.""" +"""Controller for computing Indicators.""" import logging from typing import Coroutine from geojson import Feature, FeatureCollection -from ohsome_quality_api.api.request_models import ( - ReportRequest, -) from ohsome_quality_api.indicators.base import BaseIndicator as Indicator -from ohsome_quality_api.reports.base import BaseReport as Report -from ohsome_quality_api.topics.definitions import get_topic_preset from ohsome_quality_api.topics.models import BaseTopic as Topic from ohsome_quality_api.topics.models import TopicData, TopicDefinition from ohsome_quality_api.utils.helper import get_class_from_key @@ -50,22 +45,6 @@ async def create_indicator( return await gather_with_semaphore(tasks) -async def create_report(parameters: ReportRequest, key: str) -> FeatureCollection: - """Create report(s) for features of a GeoJSON FeatureCollection.""" - bpolys = parameters.bpolys - features = [] - for i, feature in enumerate(bpolys.features): - if "id" not in feature.keys(): - feature["id"] = i - validate_area(feature) - # Reports for a FeatureCollection are not created asynchronously (as it is - # the case with indicators), because indicators of a report are created - # asynchronously - report = await _create_report(key, feature) - features.append(report.as_feature()) - return FeatureCollection(features=features) - - async def _create_indicator( key: str, feature: Feature, @@ -97,29 +76,3 @@ async def _create_indicator( indicator.result.figure = None return indicator - - -async def _create_report(key: str, feature: Feature) -> Report: - """Create a Report. - - Aggregates all indicator results and calculates an overall quality score. - - Indicators for a Report are created asynchronously utilizing semaphores. - """ - - logging.info("Creating Report...") - logging.info("Report key: {0:4}".format(key)) - logging.info("Feature id: {0:4}".format(feature.get("id", "None"))) - - report_class = get_class_from_key(class_type="report", key=key) - report = report_class(feature=feature) - - tasks: list[Coroutine] = [] - for indicator_key, topic_key in report.indicator_topic: - topic = get_topic_preset(topic_key) - tasks.append(_create_indicator(indicator_key, feature, topic)) - - report.indicators = await gather_with_semaphore(tasks) - report.combine_indicators() - - return report diff --git a/ohsome_quality_api/reports/__init__.py b/ohsome_quality_api/reports/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/base.py b/ohsome_quality_api/reports/base.py deleted file mode 100644 index ec814a42f..000000000 --- a/ohsome_quality_api/reports/base.py +++ /dev/null @@ -1,117 +0,0 @@ -from __future__ import annotations # superfluous in Python 3.10 - -import logging -from abc import ABCMeta, abstractmethod -from typing import NamedTuple - -import numpy as np -from geojson import Feature - -from ohsome_quality_api.definitions import get_attribution, get_metadata -from ohsome_quality_api.indicators.base import BaseIndicator -from ohsome_quality_api.reports.models import ReportMetadata, Result - - -class IndicatorTopic(NamedTuple): - indicator_name: str - topic_key: str - - -class BaseReport(metaclass=ABCMeta): - def __init__( - self, - feature: Feature, - indicator_topic: tuple[IndicatorTopic] = None, - blocking_red: bool = False, - blocking_undefined: bool = False, - ): - self.metadata: ReportMetadata = get_metadata("reports", type(self).__name__) - self.feature = feature - - self.indicators: list[BaseIndicator] = [] - self.indicator_topic = indicator_topic # Defines indicator+topic combinations - self.blocking_undefined = blocking_undefined - self.blocking_red = blocking_red - # Results will be written during the lifecycle of the report object (combine()) - self.result = Result() - - def as_feature(self, include_data: bool = False) -> Feature: - """Returns a GeoJSON Feature object. - - The properties of the Feature contains the attributes of all indicators. - The geometry (and properties) of the input GeoJSON object is preserved. - """ - result = self.result.dict(by_alias=True) # only attributes, no properties - result["label"] = self.result.label # label is a property - properties = { - "report": { - "metadata": self.metadata.dict(), - "result": result, - }, - "indicators": [], - } - properties["report"]["metadata"].pop("label_description", None) - - for i, indicator in enumerate(self.indicators): - properties["indicators"].append( - indicator.as_feature(include_data=include_data)["properties"] - ) - if "id" in self.feature.keys(): - return Feature( - id=self.feature.id, - geometry=self.feature.geometry, - properties=properties, - ) - else: - return Feature(geometry=self.feature.geometry, properties=properties) - - @abstractmethod - def combine_indicators(self) -> None: - """Combine indicators results and create the report result object.""" - logging.info(f"Combine indicators for report: {self.metadata.name}") - - if self.blocking_undefined: - if any(i.result.class_ is None for i in self.indicators): - self.result.class_ = None - self.result.description = self.metadata.label_description["undefined"] - return - - if self.blocking_red: - if any(i.result.class_ == 1 for i in self.indicators): - self.result.class_ = 1 - self.result.description = self.metadata.label_description["red"] - return - - if all(i.result.class_ is None for i in self.indicators): - self.result.class_ = None - self.result.description = self.metadata.label_description["undefined"] - else: - self.result.class_ = round( - np.mean( - [ - i.result.class_ - for i in self.indicators - if i.result.class_ is not None - ] - ) - ) - - if self.result.class_ in (4, 5): - self.result.description = self.metadata.label_description["green"] - elif self.result.class_ in (2, 3): - self.result.description = self.metadata.label_description["yellow"] - elif self.result.class_ == 1: - self.result.description = self.metadata.label_description["red"] - else: - self.result.description = self.metadata.label_description["undefined"] - - @classmethod - def attribution(cls) -> str: - """Data attribution as text. - - Defaults to OpenStreetMap attribution. - - This property should be overwritten by the Sub Class if additional data - attribution is necessary. - """ - return get_attribution(["OSM"]) diff --git a/ohsome_quality_api/reports/building_report/__init__.py b/ohsome_quality_api/reports/building_report/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/building_report/metadata.yaml b/ohsome_quality_api/reports/building_report/metadata.yaml deleted file mode 100644 index 8c1451682..000000000 --- a/ohsome_quality_api/reports/building_report/metadata.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -building-report: - name: Building Report - projects: - - experimental - description: >- - This report gives a general overview of the quality for buildings. - label_description: - red: >- - The report indicates low quality of the underlying OSM data. - Probably many buildings are not yet mapped. - yellow: >- - The report indicates medium quality of the underlying OSM data. - Please inspect the results for the individual indicators - to identify potential data quality concerns. - green: >- - It is likely that the buildings in this region are well mapped. - undefined: >- - Could not derive quality level. -... diff --git a/ohsome_quality_api/reports/building_report/report.py b/ohsome_quality_api/reports/building_report/report.py deleted file mode 100644 index bdd511c5f..000000000 --- a/ohsome_quality_api/reports/building_report/report.py +++ /dev/null @@ -1,25 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class BuildingReport(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = None, - blocking_undefined: bool = None, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("mapping-saturation", "building-count"), - IndicatorTopic("currentness", "building-count"), - IndicatorTopic("attribute-completeness", "building-count"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() diff --git a/ohsome_quality_api/reports/definitions.py b/ohsome_quality_api/reports/definitions.py deleted file mode 100644 index ed27f8bc9..000000000 --- a/ohsome_quality_api/reports/definitions.py +++ /dev/null @@ -1,20 +0,0 @@ -from enum import Enum - -from ohsome_quality_api.definitions import load_metadata -from ohsome_quality_api.projects.definitions import ProjectEnum -from ohsome_quality_api.reports.models import ReportMetadata - - -def get_report_keys() -> list[str]: - return list(load_metadata("reports").keys()) - - -def get_report_metadata(project: ProjectEnum = None) -> dict[str, ReportMetadata]: - reports = load_metadata("reports") - if project is not None: - return {k: v for k, v in reports.items() if project in v.projects} - else: - return reports - - -ReportEnum = Enum("ReportEnum", {name: name for name in get_report_keys()}) diff --git a/ohsome_quality_api/reports/food_related_report/__init__.py b/ohsome_quality_api/reports/food_related_report/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/food_related_report/metadata.yaml b/ohsome_quality_api/reports/food_related_report/metadata.yaml deleted file mode 100644 index 810b66dfc..000000000 --- a/ohsome_quality_api/reports/food_related_report/metadata.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -food-related-report: - name: Food Related Report - projects: - - experimental - description: >- - This report shows the quality of food related POIs. - If one indicator shows bad quality or is undefined this report also shows bad quality or is undefined respectively. - label_description: - red: >- - The indicators show a bad quality. - The food related POIs seems to be not sufficient mapped in this region. - yellow: >- - At least one indicator shows only medium quality. - You should inspect the results for the individual indicators - to identify potential data quality concerns. - green: >- - All indicators show a good quality. - The food related POIs in this regions seems to be sufficient mapped. - undefined: >- - Could not derive quality level. diff --git a/ohsome_quality_api/reports/food_related_report/report.py b/ohsome_quality_api/reports/food_related_report/report.py deleted file mode 100644 index 07071a207..000000000 --- a/ohsome_quality_api/reports/food_related_report/report.py +++ /dev/null @@ -1,43 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.definitions import get_attribution -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class FoodRelatedReport(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = True, - blocking_undefined: bool = True, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("mapping-saturation", "local_food_shops"), - IndicatorTopic("currentness", "local_food_shops"), - IndicatorTopic("mapping-saturation", "fast_food_restaurants"), - IndicatorTopic("currentness", "fast_food_restaurants"), - IndicatorTopic("mapping-saturation", "restaurants"), - IndicatorTopic("currentness", "restaurants"), - IndicatorTopic("mapping-saturation", "supermarkets"), - IndicatorTopic("currentness", "supermarkets"), - IndicatorTopic("mapping-saturation", "convenience_stores"), - IndicatorTopic("currentness", "convenience_stores"), - IndicatorTopic("mapping-saturation", "pubs_and_biergartens"), - IndicatorTopic("currentness", "pubs_and_biergartens"), - IndicatorTopic("mapping-saturation", "alcohol_and_beverages"), - IndicatorTopic("currentness", "alcohol_and_beverages"), - IndicatorTopic("mapping-saturation", "sweets_and_pasteries"), - IndicatorTopic("currentness", "sweets_and_pasteries"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() - - @classmethod - def attribution(cls) -> str: - return get_attribution(["OSM"]) diff --git a/ohsome_quality_api/reports/map_action_poc/__init__.py b/ohsome_quality_api/reports/map_action_poc/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/map_action_poc/metadata.yaml b/ohsome_quality_api/reports/map_action_poc/metadata.yaml deleted file mode 100644 index 699ec01eb..000000000 --- a/ohsome_quality_api/reports/map_action_poc/metadata.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -map-action-poc: - name: MapAction POC Country Overview - projects: - - experimental - description: >- - This report is a proof of concept (POC) data quality report for a MapAction country overview product. - label_description: - red: >- - The data quality in this region is low. - It is very likely that this regions has not been completely - mapped in OSM. - yellow: >- - At least one indicator shows only medium quality. - You should inspect the results for the individual indicators - to identify potential data quality concerns. - green: >- - All indicators show a good quality. - The data in this region seems to be good for creating a MapAction country overview product. - undefined: >- - Could not derive quality level. diff --git a/ohsome_quality_api/reports/map_action_poc/report.py b/ohsome_quality_api/reports/map_action_poc/report.py deleted file mode 100644 index 65deec59e..000000000 --- a/ohsome_quality_api/reports/map_action_poc/report.py +++ /dev/null @@ -1,32 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class MapActionPoc(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = None, - blocking_undefined: bool = None, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("mapping-saturation", "mapaction-settlements-count"), - IndicatorTopic("mapping-saturation", "mapaction-major-roads-length"), - IndicatorTopic("mapping-saturation", "mapaction-rail-length"), - IndicatorTopic("mapping-saturation", "mapaction-lakes-area"), - IndicatorTopic("mapping-saturation", "mapaction-rivers-length"), - IndicatorTopic("currentness", "mapaction-settlements-count"), - IndicatorTopic("currentness", "mapaction-major-roads-length"), - IndicatorTopic("currentness", "mapaction-rail-length"), - IndicatorTopic("currentness", "mapaction-lakes-count"), - IndicatorTopic("currentness", "mapaction-rivers-length"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() diff --git a/ohsome_quality_api/reports/minimal/__init__.py b/ohsome_quality_api/reports/minimal/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/minimal/metadata.yaml b/ohsome_quality_api/reports/minimal/metadata.yaml deleted file mode 100644 index 4f4ec0fe5..000000000 --- a/ohsome_quality_api/reports/minimal/metadata.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -minimal: - name: Minimal - projects: - - misc - description: >- - This report shows the quality for two indicators: - Mapping Saturation and Currentness. - It's main function is to test the interactions between - database, api and dashboard. - label_description: - red: >- - The data quality in this region is low. - It is very likely that this regions has not been completely - mapped in OSM. - yellow: >- - At least one indicator shows only medium quality. - You should inspect the results for the individual indicators - to identify potential data quality concerns. - green: >- - All indicators show a good quality. - The data in this regions seems to be completely mapped. - undefined: >- - Could not derive quality level. diff --git a/ohsome_quality_api/reports/minimal/report.py b/ohsome_quality_api/reports/minimal/report.py deleted file mode 100644 index 6c42cc90b..000000000 --- a/ohsome_quality_api/reports/minimal/report.py +++ /dev/null @@ -1,29 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.definitions import get_attribution -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class Minimal(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = None, - blocking_undefined: bool = None, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("mapping-saturation", "building-count"), - IndicatorTopic("currentness", "building-count"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() - - @classmethod - def attribution(cls) -> str: - return get_attribution(["OSM"]) diff --git a/ohsome_quality_api/reports/models.py b/ohsome_quality_api/reports/models.py deleted file mode 100644 index 0748ec8f8..000000000 --- a/ohsome_quality_api/reports/models.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Literal - -from pydantic import BaseModel, ConfigDict - -from ohsome_quality_api.projects.definitions import ProjectEnum -from ohsome_quality_api.utils.helper import snake_to_lower_camel - - -class ReportMetadata(BaseModel): - """Metadata of a report as defined in the metadata.yaml file""" - - name: str - description: str - label_description: dict - projects: list[ProjectEnum] - model_config = ConfigDict( - alias_generator=snake_to_lower_camel, - title="Metadata", - frozen=True, - extra="forbid", - populate_by_name=True, - ) - - -class Result(BaseModel): - """The result of the Report.""" - - class_: Literal[1, 2, 3, 4, 5] | None = None - description: str = "" - model_config = ConfigDict( - alias_generator=snake_to_lower_camel, - extra="forbid", - populate_by_name=True, - ) - - @property - def label(self) -> Literal["green", "yellow", "red", "undefined"]: - labels = {1: "red", 2: "yellow", 3: "yellow", 4: "green", 5: "green"} - return labels.get(self.class_, "undefined") diff --git a/ohsome_quality_api/reports/multilevel_currentness/__init__.py b/ohsome_quality_api/reports/multilevel_currentness/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/multilevel_currentness/metadata.yaml b/ohsome_quality_api/reports/multilevel_currentness/metadata.yaml deleted file mode 100644 index 59dc119e9..000000000 --- a/ohsome_quality_api/reports/multilevel_currentness/metadata.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -multilevel-currentness: - name: Multilevel Currentness - projects: - - experimental - description: >- - This report shows the currentness of four major map features (https://wiki.openstreetmap.org/wiki/Map_features): - buildings, land-use and land-cover, points of interest and infrastructure. - label_description: - red: >- - The general currentness for major map features in this region is low indicating that most of the major map features have not been updated for many years. - yellow: >- - The currentness of major map features in this region is mediocre. The results for each indicator should be reviewed - to determine the suitability of this region. - green: >- - Most of the major map features were edited in recent years. This indicates a high currentness in this region. - undefined: >- - The quality level could not be calculated. diff --git a/ohsome_quality_api/reports/multilevel_currentness/report.py b/ohsome_quality_api/reports/multilevel_currentness/report.py deleted file mode 100644 index dc0b0ff28..000000000 --- a/ohsome_quality_api/reports/multilevel_currentness/report.py +++ /dev/null @@ -1,31 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.definitions import get_attribution -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class MultilevelCurrentness(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = None, - blocking_undefined: bool = None, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("currentness", "infrastructure-lines"), - IndicatorTopic("currentness", "poi"), - IndicatorTopic("currentness", "lulc"), - IndicatorTopic("currentness", "building-count"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() - - @classmethod - def attribution(cls) -> str: - return get_attribution(["OSM"]) diff --git a/ohsome_quality_api/reports/multilevel_mapping_saturation/__init__.py b/ohsome_quality_api/reports/multilevel_mapping_saturation/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/multilevel_mapping_saturation/metadata.yaml b/ohsome_quality_api/reports/multilevel_mapping_saturation/metadata.yaml deleted file mode 100644 index 6d280e494..000000000 --- a/ohsome_quality_api/reports/multilevel_mapping_saturation/metadata.yaml +++ /dev/null @@ -1,16 +0,0 @@ -multilevel-mapping-saturation: - name: Multilevel Mapping Saturation - projects: - - core - description: >- - This report shows the mapping saturation of four major Map Features (https://wiki.openstreetmap.org/wiki/Map_features): buildings, land-use/land-cover, points of interest and infrastructure. - It evolved from the OSM Element Vectorisation tool (https://gitlab.gistools.geog.uni-heidelberg.de/giscience/ideal-vgi/osm-element-vectorisation). - label_description: - red: >- - The general mapping saturation for central elements in this region is low indicating a very early stage of the data. - yellow: >- - The area experiences a considerable amount of mapping but is still growing. - green: >- - This area is either well mapped or otherwise stale. - undefined: >- - The quality level could not be calculated, possibly due to no convergence in the model. diff --git a/ohsome_quality_api/reports/multilevel_mapping_saturation/report.py b/ohsome_quality_api/reports/multilevel_mapping_saturation/report.py deleted file mode 100644 index d40285b6a..000000000 --- a/ohsome_quality_api/reports/multilevel_mapping_saturation/report.py +++ /dev/null @@ -1,31 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.definitions import get_attribution -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class MultilevelMappingSaturation(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = None, - blocking_undefined: bool = None, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("mapping-saturation", "infrastructure-lines"), - IndicatorTopic("mapping-saturation", "poi"), - IndicatorTopic("mapping-saturation", "lulc"), - IndicatorTopic("mapping-saturation", "building-count"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() - - @classmethod - def attribution(cls) -> str: - return get_attribution(["OSM"]) diff --git a/ohsome_quality_api/reports/remote_mapping_level_one/__init__.py b/ohsome_quality_api/reports/remote_mapping_level_one/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/remote_mapping_level_one/report.py b/ohsome_quality_api/reports/remote_mapping_level_one/report.py deleted file mode 100644 index 1e8483433..000000000 --- a/ohsome_quality_api/reports/remote_mapping_level_one/report.py +++ /dev/null @@ -1,23 +0,0 @@ -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic -from ohsome_quality_api.utils.definitions import get_attribution - - -class RemoteMappingLevelOne(BaseReport): - def set_indicator_layer(self) -> None: - super().__init__( - indicator_topic=( - # TODO: Uncomment once implemented - # IndicatorTopic("GufComparison"], "building-area"), - IndicatorTopic("MappingSaturation", "building-count"), - IndicatorTopic("MappingSaturation", "roads"), - IndicatorTopic("Currentness", "building-count"), - IndicatorTopic("Currentness", "roads"), - ) - ) - - def combine_indicators(self) -> None: - super().combine_indicators() - - @classmethod - def attribution(cls) -> str: - return get_attribution(["OSM", "GHSL"]) diff --git a/ohsome_quality_api/reports/road_report/__init__.py b/ohsome_quality_api/reports/road_report/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/road_report/metadata.yaml b/ohsome_quality_api/reports/road_report/metadata.yaml deleted file mode 100644 index 1d48bbbc6..000000000 --- a/ohsome_quality_api/reports/road_report/metadata.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -road-report: - name: Road Report - projects: - - experimental - description: >- - This report gives a general overview of the quality for roads. - label_description: - red: >- - The report indicates low quality of the underlying OSM data. - Probably many roads are not yet mapped. - yellow: >- - The report indicates medium quality of the underlying OSM data. - Please inspect the results for the individual indicators - to identify potential data quality concerns. - green: >- - It is likely that the roads in this region are well mapped. - undefined: >- - Could not derive quality level. diff --git a/ohsome_quality_api/reports/road_report/report.py b/ohsome_quality_api/reports/road_report/report.py deleted file mode 100644 index cc68717db..000000000 --- a/ohsome_quality_api/reports/road_report/report.py +++ /dev/null @@ -1,30 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.definitions import get_attribution -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class RoadReport(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = None, - blocking_undefined: bool = None, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("mapping-saturation", "roads"), - IndicatorTopic("currentness", "roads"), - IndicatorTopic("attribute-completeness", "roads"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() - - @classmethod - def attribution(cls) -> str: - return get_attribution(["OSM"]) diff --git a/ohsome_quality_api/reports/sketchmap_fitness/__init__.py b/ohsome_quality_api/reports/sketchmap_fitness/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ohsome_quality_api/reports/sketchmap_fitness/metadata.yaml b/ohsome_quality_api/reports/sketchmap_fitness/metadata.yaml deleted file mode 100644 index 296ad7749..000000000 --- a/ohsome_quality_api/reports/sketchmap_fitness/metadata.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -sketchmap-fitness: - name: Sketch Map Fitness - projects: - - sketchmap - description: >- - The Sketch Map Fitness Report consists of four data quality indicators - (mapping saturation of major roads, currentness of major roads and - amenities, density of landmarks). The report tells you whether - you should expect potential problems when using OSM-based Sketch - Maps for the area of interest. - label_description: - red: >- - The report indicates low quality of the underlying OSM data. - It is likely that it is not possible to use - the Sketch Map Tool for this area without first improving the local OSM data, - e.g. through a Mapathon. - yellow: >- - The report indicates medium quality of the underlying OSM data. - You should inspect the results for the individual indicators - to identify potential data quality concerns. - green: >- - This region seems to be well suited for mapping - using the Sketch Map Tool. - undefined: >- - Could not derive quality level. diff --git a/ohsome_quality_api/reports/sketchmap_fitness/report.py b/ohsome_quality_api/reports/sketchmap_fitness/report.py deleted file mode 100644 index d995b4e87..000000000 --- a/ohsome_quality_api/reports/sketchmap_fitness/report.py +++ /dev/null @@ -1,26 +0,0 @@ -from geojson import Feature - -from ohsome_quality_api.reports.base import BaseReport, IndicatorTopic - - -class SketchmapFitness(BaseReport): - def __init__( - self, - feature: Feature, - blocking_red: bool = None, - blocking_undefined: bool = None, - ): - super().__init__( - indicator_topic=( - IndicatorTopic("mapping-saturation", "roads"), - IndicatorTopic("currentness", "roads"), - IndicatorTopic("currentness", "amenities"), - IndicatorTopic("density", "landmarks"), - ), - feature=feature, - blocking_red=blocking_red, - blocking_undefined=blocking_undefined, - ) - - def combine_indicators(self) -> None: - super().combine_indicators() diff --git a/tests/conftest.py b/tests/conftest.py index 9c3cff5e7..142a30786 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,7 +18,6 @@ load_quality_dimensions, ) from ohsome_quality_api.quality_dimensions.models import QualityDimension -from ohsome_quality_api.reports.models import ReportMetadata from ohsome_quality_api.topics.definitions import ( get_topic_preset, load_topic_presets, @@ -248,13 +247,3 @@ def metadata_indicator_minimal() -> dict[str, IndicatorMetadata]: @pytest.fixture def indicators_metadata() -> dict[str, IndicatorMetadata]: return load_metadata("indicators") - - -@pytest.fixture -def metadata_report_minimal() -> dict[str, ReportMetadata]: - return {"minimal": get_metadata("reports", "Minimal")} - - -@pytest.fixture -def reports_metadata() -> dict[str, ReportMetadata]: - return load_metadata("reports") diff --git a/tests/integrationtests/api/test_metadata_reports.py b/tests/integrationtests/api/test_metadata_reports.py deleted file mode 100644 index 736214097..000000000 --- a/tests/integrationtests/api/test_metadata_reports.py +++ /dev/null @@ -1,64 +0,0 @@ -from ohsome_quality_api.reports.definitions import ReportEnum - - -def test(client, response_template, metadata_report_multilevel_mapping_saturation): - response = client.get("/metadata/reports/") - assert response.status_code == 200 - - content = response.json() - result = content.pop("result") - assert content == response_template - assert ( - metadata_report_multilevel_mapping_saturation["multilevel-mapping-saturation"] - == result["multilevel-mapping-saturation"] - ) - assert "minimal" not in result.keys() - - -def test_by_key(client, response_template, metadata_report_minimal): - response = client.get("/metadata/reports/minimal") - assert response.status_code == 200 - - content = response.json() - result = content.pop("result") - assert content == response_template - assert result == metadata_report_minimal - - -def test_by_key_not_found_error(client): - response = client.get("/metadata/reports/foo") - assert response.status_code == 422 - - -def test_project_core( - client, response_template, metadata_report_multilevel_mapping_saturation -): - response = client.get("/metadata/reports/?project=core") - assert response.status_code == 200 - - content = response.json() - result = content.pop("result") - assert content == response_template - assert ( - metadata_report_multilevel_mapping_saturation["multilevel-mapping-saturation"] - == result["multilevel-mapping-saturation"] - ) - assert "minimal" not in result.keys() - - -def test_project_all( - client, - response_template, -): - response = client.get("/metadata/reports/?project=all") - assert response.status_code == 200 - - content = response.json() - result = content.pop("result") - assert content == response_template - assert len(result) == len(ReportEnum) - - -def test_project_not_found_error(client): - response = client.get("/metadata/reports/?project=foo") - assert response.status_code == 422 diff --git a/tests/integrationtests/test_base_report.py b/tests/integrationtests/test_base_report.py deleted file mode 100644 index 9acc7c319..000000000 --- a/tests/integrationtests/test_base_report.py +++ /dev/null @@ -1,100 +0,0 @@ -from unittest.mock import Mock - -import pytest - -from ohsome_quality_api.indicators.minimal.indicator import ( - Minimal as MinimalIndicator, -) -from ohsome_quality_api.reports.minimal.report import Minimal as MinimalReport - -from .utils import get_geojson_fixture, get_topic_fixture - - -class TestBaseReport: - @pytest.fixture - def feature(self): - return get_geojson_fixture("heidelberg-altstadt-feature.geojson") - - @pytest.fixture - def topic(self): - return get_topic_fixture("minimal") - - def test_as_feature(self, feature, topic): - indicator = MinimalIndicator(feature=feature, topic=topic) - report = MinimalReport(feature=feature) - for _ in report.indicator_topic: - report.indicators.append(indicator) - assert feature.is_valid - - def test_attribution_class_property(self): - assert isinstance(MinimalReport.attribution(), str) - - def test_blocking_red(self, feature, topic): - report = MinimalReport(feature, blocking_red=True) - - # Mock indicator objects with a fixed result value - for i, _ in enumerate(report.indicator_topic): - if i == 0: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - else: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 5 - report.indicators.append(indicator) - - report.combine_indicators() - assert report.result.class_ == 1 and report.result.label == "red" - - def test_blocking_undefined(self, feature, topic): - report = MinimalReport(feature, blocking_undefined=True) - - # Mock indicator objects with a fixed result value - for i, _ in enumerate(report.indicator_topic): - if i == 0: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = None - report.indicators.append(indicator) - else: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 5 - report.indicators.append(indicator) - - report.combine_indicators() - assert report.result.class_ is None and report.result.label == "undefined" - - def test_no_blocking(self, feature, topic): - report = MinimalReport(feature) - - # Mock indicator objects with a fixed result value - for i, _ in enumerate(report.indicator_topic): - if i == 0: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = None - report.indicators.append(indicator) - else: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 5 - report.indicators.append(indicator) - - report.combine_indicators() - assert report.result.label != "undefined" and report.result.label != "red" - - def test_all_indicators_undefined(self, feature, topic): - report = MinimalReport(feature, blocking_red=True) - - # Mock indicator objects with a fixed result value - for _ in enumerate(report.indicator_topic): - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = None - report.indicators.append(indicator) - - report.combine_indicators() - assert report.result.label == "undefined" and report.result.class_ is None diff --git a/tests/unittests/api/test_response_models.py b/tests/unittests/api/test_response_models.py index f4d83c037..361e6babb 100644 --- a/tests/unittests/api/test_response_models.py +++ b/tests/unittests/api/test_response_models.py @@ -9,7 +9,6 @@ IndicatorMetadataResponse, ProjectMetadataResponse, QualityDimensionMetadataResponse, - ReportMetadataResponse, TopicMetadata, TopicMetadataResponse, ) @@ -150,26 +149,3 @@ def test_indicator_metadata_response_fail(metadata_indicator_minimal): def test_indicator_metadata_coverage(bpolys): IndicatorMetadataCoverageResponse(**bpolys) - - -def test_metadata_reports(metadata_report_minimal): - response = ReportMetadataResponse(result=metadata_report_minimal) - assert response.result == metadata_report_minimal - - -def test_metadata_reports_fail(metadata_report_minimal): - with pytest.raises(ValidationError): - ReportMetadataResponse(result="") - with pytest.raises(ValidationError): - ReportMetadataResponse(result="bar") - with pytest.raises(ValidationError): - ReportMetadataResponse(result={}) - with pytest.raises(ValidationError): - ReportMetadataResponse(result={"foo": "bar"}) - with pytest.raises(ValidationError): - ReportMetadataResponse(result={"foo": metadata_report_minimal}) - - -def test_metadata_reports_list(reports_metadata): - response = ReportMetadataResponse(result=reports_metadata) - assert response.result == reports_metadata diff --git a/tests/unittests/test_definitions.py b/tests/unittests/test_definitions.py index b51d3e86c..3cf1dd01c 100644 --- a/tests/unittests/test_definitions.py +++ b/tests/unittests/test_definitions.py @@ -6,7 +6,6 @@ from ohsome_quality_api.indicators.models import ( IndicatorMetadata as IndicatorMetadata, ) -from ohsome_quality_api.reports.base import ReportMetadata as ReportMetadata class TestDefinitions(unittest.TestCase): @@ -34,13 +33,6 @@ def test_load_metadata_indicator(): assert isinstance(v, IndicatorMetadata) -def test_load_metadata_report(): - metadata = definitions.load_metadata("reports") - assert isinstance(metadata, dict) - for v in metadata.values(): - assert isinstance(v, ReportMetadata) - - def test_load_metadata_wrong_module(): with pytest.raises(AssertionError): definitions.load_metadata("foo") @@ -53,13 +45,6 @@ def test_get_metadata_indicator(): assert isinstance(metadata, IndicatorMetadata) -def test_get_metadata_report(): - metadata = definitions.get_metadata("reports", "Minimal") - assert isinstance(metadata, ReportMetadata) - with pytest.raises(KeyError): - definitions.get_metadata("reports", "") - - def test_get_metadata_wrong_class(): with pytest.raises(KeyError): definitions.get_metadata("indicators", "foo") diff --git a/tests/unittests/test_helper.py b/tests/unittests/test_helper.py index 876192675..6e7959c61 100644 --- a/tests/unittests/test_helper.py +++ b/tests/unittests/test_helper.py @@ -11,7 +11,6 @@ from ohsome_quality_api.indicators.minimal.indicator import ( Minimal as MinimalIndicator, ) -from ohsome_quality_api.reports.minimal.report import Minimal as MinimalReport from ohsome_quality_api.utils.helper import ( camel_to_hyphen, flatten_sequence, @@ -41,11 +40,6 @@ def test_name_to_class(self): MinimalIndicator, ) - self.assertIs( - get_class_from_key(class_type="report", key="minimal"), - MinimalReport, - ) - self.indicators = load_metadata("indicators") for indicator_name in self.indicators.keys(): self.assertIsNotNone( diff --git a/tests/unittests/test_report_building_report.py b/tests/unittests/test_report_building_report.py deleted file mode 100644 index 7fbf6fb4c..000000000 --- a/tests/unittests/test_report_building_report.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.building_report.report import BuildingReport - -from ..utils import load_geojson_fixture - - -class TestReportBuildingReport(unittest.TestCase): - # TODO: Test case for indicator.result undefined - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = BuildingReport(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_report_food_related_report.py b/tests/unittests/test_report_food_related_report.py deleted file mode 100644 index 303f6bffb..000000000 --- a/tests/unittests/test_report_food_related_report.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.food_related_report.report import FoodRelatedReport - -from ..utils import load_geojson_fixture - - -class TestReportFoodRelatedReport(unittest.TestCase): - # TODO: Test case for indicator.result undefined - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = FoodRelatedReport(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_report_map_action_poc.py b/tests/unittests/test_report_map_action_poc.py deleted file mode 100644 index 9f81648d1..000000000 --- a/tests/unittests/test_report_map_action_poc.py +++ /dev/null @@ -1,29 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.map_action_poc.report import MapActionPoc - -from ..utils import load_geojson_fixture - - -class TestReportMapActionPoc(unittest.TestCase): - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = MapActionPoc(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_report_minimal.py b/tests/unittests/test_report_minimal.py deleted file mode 100644 index 40b070a96..000000000 --- a/tests/unittests/test_report_minimal.py +++ /dev/null @@ -1,29 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.minimal.report import Minimal - -from ..utils import load_geojson_fixture - - -class TestReportMinimal(unittest.TestCase): - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = Minimal(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_report_multilevel_currentness.py b/tests/unittests/test_report_multilevel_currentness.py deleted file mode 100644 index c3e0831e0..000000000 --- a/tests/unittests/test_report_multilevel_currentness.py +++ /dev/null @@ -1,32 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.multilevel_currentness.report import ( - MultilevelCurrentness, -) - -from ..utils import load_geojson_fixture - - -class TestReportMultilevelCurrentness(unittest.TestCase): - # TODO: Test case for indicator.result undefined - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = MultilevelCurrentness(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_report_multilevel_mapping_saturation.py b/tests/unittests/test_report_multilevel_mapping_saturation.py deleted file mode 100644 index 7ea6f7198..000000000 --- a/tests/unittests/test_report_multilevel_mapping_saturation.py +++ /dev/null @@ -1,32 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.multilevel_mapping_saturation.report import ( - MultilevelMappingSaturation, -) - -from ..utils import load_geojson_fixture - - -class TestReportMultilevelMappingSaturation(unittest.TestCase): - # TODO: Test case for indicator.result undefined - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = MultilevelMappingSaturation(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_report_road_report.py b/tests/unittests/test_report_road_report.py deleted file mode 100644 index 35bb07978..000000000 --- a/tests/unittests/test_report_road_report.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.road_report.report import RoadReport - -from ..utils import load_geojson_fixture - - -class TestReportRoadReport(unittest.TestCase): - # TODO: Test case for indicator.result undefined - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = RoadReport(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_report_sketchmap_fitness.py b/tests/unittests/test_report_sketchmap_fitness.py deleted file mode 100644 index 0c11030b3..000000000 --- a/tests/unittests/test_report_sketchmap_fitness.py +++ /dev/null @@ -1,29 +0,0 @@ -import unittest -from unittest.mock import Mock - -from ohsome_quality_api.reports.sketchmap_fitness.report import SketchmapFitness - -from ..utils import load_geojson_fixture - - -class TestReportSketchmapFitness(unittest.TestCase): - def test_combine_indicators_mean(self): - feature = load_geojson_fixture("feature-germany-heidelberg.geojson") - report = SketchmapFitness(feature) - - # Mock indicator objects with a fixed result value - for _ in report.indicator_topic: - indicator = Mock() - indicator.result = Mock() - indicator.result.class_ = 1 - report.indicators.append(indicator) - - report.combine_indicators() - - self.assertIsNotNone(report.result.label) - self.assertIsNotNone(report.result.description) - self.assertEqual(report.result.class_, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unittests/test_reports_definitions.py b/tests/unittests/test_reports_definitions.py deleted file mode 100644 index db58e6888..000000000 --- a/tests/unittests/test_reports_definitions.py +++ /dev/null @@ -1,21 +0,0 @@ -from ohsome_quality_api.reports import definitions, models - - -def test_get_report_names(): - names = definitions.get_report_keys() - assert isinstance(names, list) - - -def test_get_report_definitions_with_project(): - reports = definitions.get_report_metadata("core") - assert isinstance(reports, dict) - for report in reports.values(): - assert isinstance(report, models.ReportMetadata) - assert report.project == "core" - - -def test_get_report_definitions(): - reports = definitions.get_report_metadata() - assert isinstance(reports, dict) - for report in reports.values(): - assert isinstance(report, models.ReportMetadata) From 98d70ce452185a66c2f153f7927ec7d548e6b146 Mon Sep 17 00:00:00 2001 From: Reifenrath Date: Wed, 28 Aug 2024 14:18:43 +0200 Subject: [PATCH 2/5] updated the changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27bdc5902..a31b14e42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Current Main +### Breaking Changes + +- report endpoint: has been deleted ([#818]) + +[#818]: https://github.com/GIScience/ohsome-quality-api/pull/818 ## Release 1.4.0 From dc34a3dba5757fc027a2eff739339fb13fef33cb Mon Sep 17 00:00:00 2001 From: Gigaszi Date: Wed, 28 Aug 2024 15:40:15 +0200 Subject: [PATCH 3/5] cleanup: remove remaining tests and fix failing ones --- .../api/test_ohsome_timeout.py | 28 +++----- .../api/test_report_geojson_io.py | 68 ------------------- tests/integrationtests/test_oqt.py | 9 --- 3 files changed, 9 insertions(+), 96 deletions(-) delete mode 100644 tests/integrationtests/api/test_report_geojson_io.py diff --git a/tests/integrationtests/api/test_ohsome_timeout.py b/tests/integrationtests/api/test_ohsome_timeout.py index 17a058421..bb13fb052 100644 --- a/tests/integrationtests/api/test_ohsome_timeout.py +++ b/tests/integrationtests/api/test_ohsome_timeout.py @@ -35,22 +35,12 @@ def test_ohsome_timeout(client, bpolys): request=httpx.Request("POST", "https://www.example.org/"), ) - for endpoint, parameters in ( - ( - "/reports/minimal", - { - "bpolys": bpolys, - }, - ), - ( - "/indicators/minimal", - { - "bpolys": bpolys, - "topic": "minimal", - }, - ), - ): - response = client.post(endpoint, json=parameters) - assert response.status_code == 422 - content = response.json() - assert content["type"] == "OhsomeApiError" + endpoint = "/indicators/minimal" + parameters = { + "bpolys": bpolys, + "topic": "minimal", + } + response = client.post(endpoint, json=parameters) + assert response.status_code == 422 + content = response.json() + assert content["type"] == "OhsomeApiError" diff --git a/tests/integrationtests/api/test_report_geojson_io.py b/tests/integrationtests/api/test_report_geojson_io.py deleted file mode 100644 index 3cfac18de..000000000 --- a/tests/integrationtests/api/test_report_geojson_io.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -Testing FastAPI Applications: -https://fastapi.tiangolo.com/tutorial/testing/ -""" - -import unittest - -import geojson -from fastapi.testclient import TestClient - -from ohsome_quality_api.api.api import app -from tests.integrationtests.api.response_schema import ( - get_featurecollection_schema, - get_general_schema, - get_report_feature_schema, -) -from tests.integrationtests.utils import get_geojson_fixture, oqapi_vcr -from tests.utils import load_geojson_fixture - - -class TestApiReportIo(unittest.TestCase): - def setUp(self): - self.client = TestClient(app) - self.endpoint = "/reports/minimal" - self.featurecollection = load_geojson_fixture( - "feature-collection-germany-heidelberg.geojson" - ) - self.general_schema = get_general_schema() - self.feature_schema = get_report_feature_schema() - self.featurecollection_schema = get_featurecollection_schema() - - def run_tests(self, response) -> None: - self.assertEqual(response.status_code, 200) - self.assertEqual(response.headers["content-type"], "application/geo+json") - - response_content = geojson.loads(response.content) - self.assertTrue(response_content.is_valid) # Valid GeoJSON? - self.assertTrue(self.general_schema.is_valid(response_content)) - self.assertTrue(self.feature_schema.is_valid(response_content)) - - def post_response(self, bpoly): - """Return HTTP POST response""" - data = {"bpolys": bpoly} - return self.client.post(self.endpoint, json=data) - - @oqapi_vcr.use_cassette() - def test_report_bpolys_featurecollection(self): - response = self.post_response(self.featurecollection) - self.assertEqual(response.status_code, 200) - - response_geojson = geojson.loads(response.content) - self.assertTrue(response_geojson.is_valid) # Valid GeoJSON? - - response_content = response.json() - self.assertTrue(self.general_schema.is_valid(response_content)) - self.assertTrue(self.featurecollection_schema.is_valid(response_content)) - for feature in response_content["features"]: - self.assertTrue(self.feature_schema.is_valid(feature)) - - @oqapi_vcr.use_cassette() - def test_report_bpolys_size_limit(self): - feature = get_geojson_fixture("europe.geojson") - response = self.post_response(feature) - self.assertEqual(response.status_code, 422) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/integrationtests/test_oqt.py b/tests/integrationtests/test_oqt.py index ce5abfa48..a368a8bf0 100644 --- a/tests/integrationtests/test_oqt.py +++ b/tests/integrationtests/test_oqt.py @@ -87,15 +87,6 @@ def test_create_indicator_private_include_figure(bpolys, topic_minimal): assert indicator.result.figure is None -@oqapi_vcr.use_cassette -def test_create_report_private(feature): - """Minimal viable request for a single bpoly.""" - report = asyncio.run(oqt._create_report("minimal", feature)) - assert report.result.label is not None - assert report.result.class_ is not None - assert report.result.description is not None - - @mock.patch.dict("os.environ", {"OQAPI_GEOM_SIZE_LIMIT": "1"}, clear=True) @oqapi_vcr.use_cassette def test_create_indicator_size_limit_bpolys(bpolys, topic_minimal): From 74152a46847b52943992acbe79105d394486a084 Mon Sep 17 00:00:00 2001 From: JanReifenrath Date: Tue, 3 Sep 2024 12:55:19 +0200 Subject: [PATCH 4/5] removed some final references to reports --- ohsome_quality_api/api/request_models.py | 5 --- ohsome_quality_api/definitions.py | 20 ++++++------ ohsome_quality_api/utils/helper.py | 2 +- tests/integrationtests/api/conftest.py | 31 ------------------- tests/integrationtests/api/response_schema.py | 2 +- .../api/test_ohsome_timeout.py | 3 +- 6 files changed, 13 insertions(+), 50 deletions(-) diff --git a/ohsome_quality_api/api/request_models.py b/ohsome_quality_api/api/request_models.py index c4e8ce63f..c6977e78b 100644 --- a/ohsome_quality_api/api/request_models.py +++ b/ohsome_quality_api/api/request_models.py @@ -80,8 +80,3 @@ class IndicatorDataRequest(BaseBpolys): topic: TopicData = Field(..., title="Topic", alias="topic") include_figure: bool = True include_data: bool = False - - -class ReportRequest(BaseBpolys): - pass - # include_data: bool = False diff --git a/ohsome_quality_api/definitions.py b/ohsome_quality_api/definitions.py index 9191f60a2..a05510cd0 100644 --- a/ohsome_quality_api/definitions.py +++ b/ohsome_quality_api/definitions.py @@ -50,19 +50,19 @@ class Color(Enum): def load_metadata( - module_name: Literal["indicators", "reports"], + module_name: Literal["indicators"], ) -> dict[str, IndicatorMetadata]: - """Read metadata of all indicators or reports from YAML files. + """Read metadata of all indicators from YAML files. - Those text files are located in the directory of each indicator/report. + Those text files are located in the directory of each indicator. Args: - module_name: Either indicators or reports. + module_name: indicators. Returns: - A Dict with the class names of the indicators/reports + A Dict with the class names of the indicators as keys and metadata as values. """ - assert module_name == "indicators" or module_name == "reports" + assert module_name == "indicators" directory = get_module_dir("ohsome_quality_api.{}".format(module_name)) files = glob.glob(directory + "/**/metadata.yaml", recursive=True) raw = {} @@ -78,15 +78,15 @@ def load_metadata( def get_metadata( - module_name: Literal["indicators", "reports"], class_name: str + module_name: Literal["indicators"], class_name: str ) -> IndicatorMetadata: - """Get metadata of an indicator or report based on its class name. + """Get metadata of an indicator based on its class name. This is implemented outside the metadata class to be able to access metadata of all - indicators/reports without instantiating of those. + indicators without instantiating of those. Args: - module_name: Either indicators or reports. + module_name: indicators. class_name: Class name of an indicator (camel case). """ metadata = load_metadata(module_name) diff --git a/ohsome_quality_api/utils/helper.py b/ohsome_quality_api/utils/helper.py index 7c694559a..4bab9577b 100644 --- a/ohsome_quality_api/utils/helper.py +++ b/ohsome_quality_api/utils/helper.py @@ -17,7 +17,7 @@ def get_class_from_key(class_type: str, key: str): - """Convert indicator or report key to the class name.""" + """Convert indicator key to the class name.""" # Alternatives: # - Hard code import of classes # - Dynamically import all classes in package diff --git a/tests/integrationtests/api/conftest.py b/tests/integrationtests/api/conftest.py index 91d150d71..b1290a6d5 100644 --- a/tests/integrationtests/api/conftest.py +++ b/tests/integrationtests/api/conftest.py @@ -67,22 +67,6 @@ def metadata_indicator_mapping_saturation(): } -@pytest.fixture -def metadata_report_multilevel_mapping_saturation(): - return { - "multilevel-mapping-saturation": { - "name": "Multilevel Mapping Saturation", - "description": "This report shows the mapping saturation of four major " - + "Map Features (https://wiki.openstreetmap.org/wiki/Map_features): " - + "buildings, land-use/land-cover, points of interest and infrastructure. " - + "It evolved from the OSM Element Vectorisation tool (https://gitlab." - + "gistools.geog.uni-heidelberg.de/giscience/ideal-vgi/osm-element-" - + "vectorisation).", - "projects": ["core"], - } - } - - @pytest.fixture def metadata_quality_dimension(): return { @@ -135,21 +119,6 @@ def metadata_indicator_minimal(): } -@pytest.fixture -def metadata_report_minimal(): - return { - "minimal": { - "name": "Minimal", - "description": ( - "This report shows the quality for two indicators: Mapping Saturation " - + "and Currentness. It's main function is to test the interactions " - + "between database, api and dashboard." - ), - "projects": ["misc"], - } - } - - @pytest.fixture def metadata_attribute_clc_leaf_type(): return { diff --git a/tests/integrationtests/api/response_schema.py b/tests/integrationtests/api/response_schema.py index 2fb652b69..39cdced54 100644 --- a/tests/integrationtests/api/response_schema.py +++ b/tests/integrationtests/api/response_schema.py @@ -49,7 +49,7 @@ def get_general_schema() -> Schema: def get_result_schema() -> Schema: """Response schema for all endpoints. - Excluded are the endpoints `/indicator` and `/report`. + Excluded is the endpoint `/indicator`. """ return Schema({"result": list}, ignore_extra_keys=True) diff --git a/tests/integrationtests/api/test_ohsome_timeout.py b/tests/integrationtests/api/test_ohsome_timeout.py index bb13fb052..b11b83c04 100644 --- a/tests/integrationtests/api/test_ohsome_timeout.py +++ b/tests/integrationtests/api/test_ohsome_timeout.py @@ -2,10 +2,9 @@ Testing FastAPI Applications: https://fastapi.tiangolo.com/tutorial/testing/ -Shared tests for `/indicator` and `/report` endpoints using the `bpolys` parameter. +Shared tests for `/indicator` endpoints using the `bpolys` parameter. Tests for the individual endpoints and using the `bpolys` parameter please see: - `test_api_indicator_geojson_io.py` - - `test_api_report_geojson_io.py` """ import os From 196662c1a41fa7aa23ef09811bb1a8e4de10b90e Mon Sep 17 00:00:00 2001 From: JanReifenrath Date: Tue, 3 Sep 2024 13:27:49 +0200 Subject: [PATCH 5/5] removed the last important reference to reports --- tests/integrationtests/api/response_schema.py | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/tests/integrationtests/api/response_schema.py b/tests/integrationtests/api/response_schema.py index 39cdced54..aa0d70ac0 100644 --- a/tests/integrationtests/api/response_schema.py +++ b/tests/integrationtests/api/response_schema.py @@ -72,29 +72,3 @@ def get_indicator_feature_schema() -> Schema: }, ignore_extra_keys=True, ) - - -def get_report_feature_schema() -> Schema: - schema = Schema( - { - "type": "Feature", - "geometry": dict, - Opt("id"): Or(str, int), - "properties": { - "report": { - "metadata": { - "name": str, - "description": str, - }, - "result": { - "class": Or(int, None), - "label": str, - "description": str, - }, - }, - "indicators": [get_indicator_properties_template()], - }, - }, - ignore_extra_keys=True, - ) - return schema