Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set flatten of properties to false #375

Merged
merged 4 commits into from
Jul 7, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
### Breaking Changes

- Make inclusion of indicator data in response optional ([#370])
- Per default properties of the GeoJSON response are not flat ([#375])

### How to Upgrade

- To continue to retrieve additional data of an Indicator or Report provided in an API response, you need to set the parameter `include_data` to `True` when making requests to the API ([#370])
- To continue to retrieve additional data of an Indicator or Report provided in an API response, you need to set the API request parameter `include_data` to `True` ([#370])
- To continue to retrieve the properties of the GeoJSON API response as flat list, you need to set the API request parameter `flattem` to `True` ([#375])

[#370]: https://github.com/GIScience/ohsome-quality-analyst/pull/370
[#375]: https://github.com/GIScience/ohsome-quality-analyst/pull/375

## 0.10.0

Expand Down
10 changes: 5 additions & 5 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ parameters = {
"fidField": "ogc_fid", # Optional
"includeSvg": False, # Optional
"includeHtml": False, # Optional
"flatten": True, # Optional
"flatten": False, # Optional
}
# Response using the GET method
response = requests.get(url, params=parameters)
Expand Down Expand Up @@ -82,7 +82,7 @@ parameters = {
"bpolys": bpolys,
"includeSvg": False, # Optional
"includeHtml": False, # Optional
"flatten": True, # Optional
"flatten": False, # Optional
}
response = requests.post(url, json=parameters)
```
Expand Down Expand Up @@ -160,7 +160,7 @@ parameters = {
"layer": layer,
"includeSvg": False, # Optional
"includeHtml": False, # Optional
"flatten": True, # Optional
"flatten": False, # Optional
}
response = requests.post(url, json=parameters)
```
Expand Down Expand Up @@ -241,7 +241,7 @@ parameters = {
"featureId": 3,
"includeSvg": False, # Optional
"includeHtml": False, # Optional
"flatten": True, # Optional
"flatten": False, # Optional
}
# Response using the GET method
response = requests.get(url, params=parameters)
Expand Down Expand Up @@ -272,7 +272,7 @@ parameters = {
"bpolys": bpolys,
"includeSvg": False, # Optional
"includeHtml": False, # Optional
"flatten": True, # Optional
"flatten": False, # Optional
}
response = requests.post(url, json=parameters)
```
Expand Down
2 changes: 1 addition & 1 deletion website/website/assets/js/map-en.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ function buildMap(...charts){

function handleGetQuality(response) {
console.log("response",response)
const properties = unflattenObject(response["properties"]);
const properties = response["properties"];
const report = properties["report"];
document.getElementById("resultSection").innerHTML = ''
document.querySelector("#loader1").classList.remove("spinner-1");
Expand Down
22 changes: 0 additions & 22 deletions website/website/assets/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,3 @@ function id_isValid(value, json){
}
return valid_options.includes(value)
}

// un-flatten a 1-layer object in a deep object
function unflattenObject(input, separator=".") {
const keys = Object.keys(input);
const output = {};
for (const key of keys) {
const keyParts = key.split(separator);
let entry = output;

// go through all parts except the last one
const lastIdx = keyParts.length-1;
for (let idx = 0; idx < lastIdx; ++idx) {
const part = keyParts[idx]
if (!entry[part]) {
entry[part] = {};
}
entry = entry[part];
}
entry[keyParts[lastIdx]] = input[key];
}
return output
}
4 changes: 2 additions & 2 deletions workers/ohsome_quality_analyst/api/request_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class BaseIndicator(BaseModel):
include_svg: bool = False
include_html: bool = False
include_data: bool = False
flatten: bool = True
flatten: bool = False

class Config:
"""Pydantic config class."""
Expand All @@ -54,7 +54,7 @@ class BaseReport(BaseModel):
include_svg: bool = False
include_html: bool = False
include_data: bool = False
flatten: bool = True
flatten: bool = False

class Config:
"""Pydantic config class."""
Expand Down
54 changes: 28 additions & 26 deletions workers/tests/integrationtests/api_response_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@

def get_indicator_properties_template():
return {
"metadata.name": str,
"metadata.description": str,
"layer.name": str,
"layer.description": str,
"result.timestamp_oqt": str,
"result.timestamp_osm": Or(str),
"result.value": Or(float, None),
"result.label": str,
"result.description": str,
Opt("result.svg"): str,
"metadata": {
"name": str,
"description": str,
},
"layer": {
"name": str,
"description": str,
},
"result": {
"timestamp_oqt": str,
"timestamp_osm": Or(str),
"value": Or(float, None),
"label": str,
"description": str,
Opt("svg"): str,
},
}


Expand Down Expand Up @@ -70,28 +76,24 @@ def get_indicator_feature_schema() -> Schema:


def get_report_feature_schema(number_of_indicators: int) -> Schema:
properties_template = get_indicator_properties_template()
properties = {}
for i in range(number_of_indicators):
for k, v in properties_template.items():
prefix = "indicators." + str(i) + "."
if isinstance(k, Schema):
k._prepend_schema_name(prefix)
else:
k = prefix + k
properties.update({k: v})
schema = Schema(
{
"type": "Feature",
"geometry": dict,
Opt("id"): Or(str, int),
"properties": {
"report.metadata.name": str,
"report.metadata.description": str,
"report.result.value": float,
"report.result.label": str,
"report.result.description": str,
**properties,
"report": {
"metadata": {
"name": str,
"description": str,
},
"result": {
"value": float,
"label": str,
"description": str,
},
},
"indicators": [get_indicator_properties_template()],
},
},
ignore_extra_keys=True,
Expand Down
48 changes: 30 additions & 18 deletions workers/tests/integrationtests/test_api_indicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def test_indicator_include_svg_true(self):
)
response = self.client.get(url)
result = response.json()
self.assertIn("result.svg", list(result["properties"].keys()))
assert "svg" in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_include_svg_false(self):
Expand All @@ -156,7 +156,7 @@ def test_indicator_include_svg_false(self):
)
response = self.client.get(url)
result = response.json()
self.assertNotIn("result.svg", list(result["properties"].keys()))
assert "svg" not in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_include_svg_default(self):
Expand All @@ -172,7 +172,7 @@ def test_indicator_include_svg_default(self):
)
response = self.client.get(url)
result = response.json()
self.assertNotIn("result.svg", list(result["properties"].keys()))
assert "svg" not in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_invalid_layer(self):
Expand Down Expand Up @@ -205,7 +205,7 @@ def test_indicator_include_html_true(self):
)
response = self.client.get(url)
result = response.json()
self.assertIn("result.html", list(result["properties"].keys()))
assert "html" in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_include_html_false(self):
Expand All @@ -222,7 +222,7 @@ def test_indicator_include_html_false(self):
)
response = self.client.get(url)
result = response.json()
self.assertNotIn("result.html", list(result["properties"].keys()))
assert "html" not in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_include_html_default(self):
Expand All @@ -238,11 +238,11 @@ def test_indicator_include_html_default(self):
)
response = self.client.get(url)
result = response.json()
self.assertNotIn("result.html", list(result["properties"].keys()))
assert "html" not in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_flatten_default(self):
url = "/indicator?name={0}&layerName={1}&dataset={2}" "&featureId={3}".format(
url = "/indicator?name={0}&layerName={1}&dataset={2}&featureId={3}".format(
self.indicator_name,
self.layer_name,
self.dataset,
Expand All @@ -251,7 +251,8 @@ def test_indicator_flatten_default(self):
response = self.client.get(url)
result = response.json()
# Check flat result value
self.assertIn("result.value", result["properties"].keys())
assert "result.value" not in result["properties"]
assert "value" in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_flatten_true(self):
Expand All @@ -262,15 +263,15 @@ def test_indicator_flatten_true(self):
self.layer_name,
self.dataset,
self.feature_id,
False,
True,
)
)
response = self.client.get(url)
result = response.json()
self.assertIn("value", result["properties"]["result"])
assert "result.value" in result["properties"]

@oqt_vcr.use_cassette()
def test_indicator_include_data_default(self):
def test_indicator_flatten_false(self):
url = (
"/indicator?name={0}&layerName={1}&dataset={2}"
"&featureId={3}&flatten={4}".format(
Expand All @@ -283,41 +284,52 @@ def test_indicator_include_data_default(self):
)
response = self.client.get(url)
result = response.json()
assert "data" not in result["properties"].keys()
assert "result.value" not in result["properties"]
assert "value" in result["properties"]["result"]

@oqt_vcr.use_cassette()
def test_indicator_include_data_default(self):
url = "/indicator?name={0}&layerName={1}&dataset={2}" "&featureId={3}".format(
self.indicator_name,
self.layer_name,
self.dataset,
self.feature_id,
)
response = self.client.get(url)
result = response.json()
assert "data" not in result["properties"]

@oqt_vcr.use_cassette()
def test_indicator_include_data_true(self):
url = (
"/indicator?name={0}&layerName={1}&dataset={2}"
"&featureId={3}&flatten={4}&includeData={5}".format(
"&featureId={3}&includeData={4}".format(
self.indicator_name,
self.layer_name,
self.dataset,
self.feature_id,
False,
True,
)
)
response = self.client.get(url)
result = response.json()
assert "data" in result["properties"].keys()
assert "data" in result["properties"]

@oqt_vcr.use_cassette()
def test_indicator_include_data_false(self):
url = (
"/indicator?name={0}&layerName={1}&dataset={2}"
"&featureId={3}&flatten={4}&includeData={5}".format(
"&featureId={3}&includeData={4}".format(
self.indicator_name,
self.layer_name,
self.dataset,
self.feature_id,
False,
False,
)
)
response = self.client.get(url)
result = response.json()
assert "data" not in result["properties"].keys()
assert "data" not in result["properties"]


if __name__ == "__main__":
Expand Down
11 changes: 6 additions & 5 deletions workers/tests/integrationtests/test_api_indicator_geojson_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def test_indicator_include_svg(self):
}
response = self.client.post(self.endpoint, json=parameters)
result = response.json()
self.assertIn("result.svg", list(result["properties"].keys()))
assert "svg" in result["properties"]["result"]

parameters = {
"name": self.indicator_name,
Expand All @@ -123,7 +123,7 @@ def test_indicator_include_svg(self):
}
response = self.client.post(self.endpoint, json=parameters)
result = response.json()
self.assertNotIn("result.svg", list(result["properties"].keys()))
assert "svg" not in result["properties"]["result"]

parameters = {
"name": self.indicator_name,
Expand All @@ -146,7 +146,8 @@ def test_indicator_include_html(self):
}
response = self.client.post(self.endpoint, json=parameters)
result = response.json()
self.assertIn("result.html", list(result["properties"].keys()))
assert "html" in result["properties"]["result"]

parameters = {
"name": self.indicator_name,
"layerName": self.layer_name,
Expand All @@ -156,7 +157,7 @@ def test_indicator_include_html(self):
}
response = self.client.post(self.endpoint, json=parameters)
result = response.json()
self.assertNotIn("result.html", list(result["properties"].keys()))
assert "html" not in result["properties"]["result"]

parameters = {
"name": self.indicator_name,
Expand All @@ -165,7 +166,7 @@ def test_indicator_include_html(self):
}
response = self.client.post(self.endpoint, json=parameters)
result = response.json()
self.assertNotIn("result.html", list(result["properties"].keys()))
assert "html" not in result["properties"]["result"]

def test_indicator_layer_data(self):
"""Test parameter Layer with data attached.
Expand Down
Loading