mirror of
https://github.com/simonw/datasette.git
synced 2026-10-18 15:26:57 +02:00
Replace infinities in facet results with null in JSON output, closes #2954
This commit is contained in:
parent
74f178cd12
commit
f63d647de0
2 changed files with 55 additions and 2 deletions
|
|
@ -30,6 +30,10 @@ def convert_specific_columns_to_json(rows, columns, json_cols):
|
|||
return new_rows
|
||||
|
||||
|
||||
def _facet_without_infinites(facet):
|
||||
return {**facet, "results": [remove_infinites(r) for r in facet["results"]]}
|
||||
|
||||
|
||||
def json_renderer(request, args, data, error, truncated=None):
|
||||
"""Render a response as JSON"""
|
||||
status_code = 200
|
||||
|
|
@ -44,8 +48,23 @@ def json_renderer(request, args, data, error, truncated=None):
|
|||
)
|
||||
|
||||
# unless _json_infinity=1 requested, replace infinity with None
|
||||
if "rows" in data and not value_as_boolean(args.get("_json_infinity", "0")):
|
||||
data["rows"] = [remove_infinites(row) for row in data["rows"]]
|
||||
if not value_as_boolean(args.get("_json_infinity", "0")):
|
||||
if "rows" in data:
|
||||
data["rows"] = [remove_infinites(row) for row in data["rows"]]
|
||||
# Facet values and labels can be infinities too
|
||||
if isinstance(data.get("facet_results"), dict):
|
||||
data["facet_results"] = {
|
||||
**data["facet_results"],
|
||||
"results": {
|
||||
name: _facet_without_infinites(facet)
|
||||
for name, facet in data["facet_results"]["results"].items()
|
||||
},
|
||||
}
|
||||
if isinstance(data.get("sorted_facet_results"), list):
|
||||
data["sorted_facet_results"] = [
|
||||
_facet_without_infinites(facet)
|
||||
for facet in data["sorted_facet_results"]
|
||||
]
|
||||
|
||||
# Deal with the _shape option
|
||||
shape = args.get("_shape", "objects")
|
||||
|
|
|
|||
|
|
@ -1290,6 +1290,40 @@ async def test_infinity_returned_as_null(ds_client):
|
|||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("extra", ("facet_results", "sorted_facet_results"))
|
||||
async def test_infinity_facet_values_returned_as_null(ds_client, extra):
|
||||
# https://github.com/simonw/datasette/issues/2954
|
||||
response = await ds_client.get(
|
||||
"/fixtures/infinity.json?_facet=value&_extra=" + extra
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def reject_constant(token):
|
||||
raise ValueError(f"Non-JSON numeric literal: {token}")
|
||||
|
||||
data = json.loads(response.text, parse_constant=reject_constant)
|
||||
facets = data[extra]
|
||||
facet = facets["results"]["value"] if extra == "facet_results" else facets[0]
|
||||
values = sorted(
|
||||
((r["value"], r["label"]) for r in facet["results"]),
|
||||
key=lambda pair: (pair[0] is not None, pair),
|
||||
)
|
||||
assert values == [(None, None), (None, None), (1.5, 1.5)]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_infinity_facet_values_returned_as_invalid_json_if_requested(ds_client):
|
||||
response = await ds_client.get(
|
||||
"/fixtures/infinity.json?_facet=value&_extra=facet_results&_json_infinity=1"
|
||||
)
|
||||
values = {
|
||||
r["value"]
|
||||
for r in response.json()["facet_results"]["results"]["value"]["results"]
|
||||
}
|
||||
assert values == {float("inf"), float("-inf"), 1.5}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_infinity_returned_as_invalid_json_if_requested(ds_client):
|
||||
response = await ds_client.get(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue