mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
?_json_infinity=1 for handling Infinity/-Infinity - fixes #332
This commit is contained in:
parent
b320f58d13
commit
700d83d8ad
5 changed files with 64 additions and 2 deletions
|
|
@ -864,3 +864,15 @@ class LimitedWriter:
|
||||||
self.limit_bytes
|
self.limit_bytes
|
||||||
))
|
))
|
||||||
self.writer.write(bytes)
|
self.writer.write(bytes)
|
||||||
|
|
||||||
|
|
||||||
|
_infinities = {float("inf"), float("-inf")}
|
||||||
|
|
||||||
|
|
||||||
|
def remove_infinites(row):
|
||||||
|
if any((c in _infinities) if isinstance(c, float) else 0 for c in row):
|
||||||
|
return [
|
||||||
|
None if (isinstance(c, float) and c in _infinities) else c
|
||||||
|
for c in row
|
||||||
|
]
|
||||||
|
return row
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,10 @@ from datasette.utils import (
|
||||||
path_from_row_pks,
|
path_from_row_pks,
|
||||||
path_with_added_args,
|
path_with_added_args,
|
||||||
path_with_format,
|
path_with_format,
|
||||||
|
remove_infinites,
|
||||||
resolve_table_and_format,
|
resolve_table_and_format,
|
||||||
to_css_class
|
to_css_class,
|
||||||
|
value_as_boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
ureg = pint.UnitRegistry()
|
ureg = pint.UnitRegistry()
|
||||||
|
|
@ -334,6 +336,12 @@ class BaseView(RenderMixin):
|
||||||
data["rows"], data["columns"], json_cols,
|
data["rows"], data["columns"], json_cols,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# unless _json_infinity=1 requested, replace infinity with None
|
||||||
|
if "rows" in data and not value_as_boolean(
|
||||||
|
request.args.get("_json_infinity", "0")
|
||||||
|
):
|
||||||
|
data["rows"] = [remove_infinites(row) for row in data["rows"]]
|
||||||
|
|
||||||
# Deal with the _shape option
|
# Deal with the _shape option
|
||||||
shape = request.args.get("_shape", "arrays")
|
shape = request.args.get("_shape", "arrays")
|
||||||
if shape == "arrayfirst":
|
if shape == "arrayfirst":
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,12 @@ querystring arguments:
|
||||||
|
|
||||||
Compare `this query without the argument <https://fivethirtyeight.datasettes.com/fivethirtyeight.json?sql=select+%27{%22this+is%22%3A+%22a+json+object%22}%27+as+d&_shape=array>`_ to `this query using the argument <https://fivethirtyeight.datasettes.com/fivethirtyeight.json?sql=select+%27{%22this+is%22%3A+%22a+json+object%22}%27+as+d&_shape=array&_json=d>`_
|
Compare `this query without the argument <https://fivethirtyeight.datasettes.com/fivethirtyeight.json?sql=select+%27{%22this+is%22%3A+%22a+json+object%22}%27+as+d&_shape=array>`_ to `this query using the argument <https://fivethirtyeight.datasettes.com/fivethirtyeight.json?sql=select+%27{%22this+is%22%3A+%22a+json+object%22}%27+as+d&_shape=array&_json=d>`_
|
||||||
|
|
||||||
|
``?_json_infinity=on``
|
||||||
|
If your data contains infinity or -infinity values, Datasette will replace
|
||||||
|
them with None when returning them as JSON. If you pass ``_json_infinity=1``
|
||||||
|
Datasette will instead return them as ``Infinity`` or ``-Infinity`` which is
|
||||||
|
invalid JSON but can be processed by some custom JSON parsers.
|
||||||
|
|
||||||
``?_timelimit=MS``
|
``?_timelimit=MS``
|
||||||
Sets a custom time limit for the query in ms. You can use this for optimistic
|
Sets a custom time limit for the query in ms. You can use this for optimistic
|
||||||
queries where you would like Datasette to give up if the query takes too
|
queries where you would like Datasette to give up if the query takes too
|
||||||
|
|
|
||||||
|
|
@ -367,6 +367,15 @@ CREATE TABLE [select] (
|
||||||
);
|
);
|
||||||
INSERT INTO [select] VALUES ('group', 'having', 'and');
|
INSERT INTO [select] VALUES ('group', 'having', 'and');
|
||||||
|
|
||||||
|
CREATE TABLE infinity (
|
||||||
|
value REAL
|
||||||
|
);
|
||||||
|
INSERT INTO infinity VALUES
|
||||||
|
(1e999),
|
||||||
|
(-1e999),
|
||||||
|
(1.5)
|
||||||
|
;
|
||||||
|
|
||||||
CREATE TABLE facet_cities (
|
CREATE TABLE facet_cities (
|
||||||
id integer primary key,
|
id integer primary key,
|
||||||
name text
|
name text
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ def test_homepage(app_client):
|
||||||
assert response.json.keys() == {'fixtures': 0}.keys()
|
assert response.json.keys() == {'fixtures': 0}.keys()
|
||||||
d = response.json['fixtures']
|
d = response.json['fixtures']
|
||||||
assert d['name'] == 'fixtures'
|
assert d['name'] == 'fixtures'
|
||||||
assert d['tables_count'] == 19
|
assert d['tables_count'] == 20
|
||||||
|
|
||||||
|
|
||||||
def test_database_page(app_client):
|
def test_database_page(app_client):
|
||||||
|
|
@ -153,6 +153,15 @@ def test_database_page(app_client):
|
||||||
'label_column': None,
|
'label_column': None,
|
||||||
'fts_table': None,
|
'fts_table': None,
|
||||||
'primary_keys': ['pk'],
|
'primary_keys': ['pk'],
|
||||||
|
}, {
|
||||||
|
"name": "infinity",
|
||||||
|
"columns": ["value"],
|
||||||
|
"count": 3,
|
||||||
|
"primary_keys": [],
|
||||||
|
"label_column": None,
|
||||||
|
"hidden": False,
|
||||||
|
"fts_table": None,
|
||||||
|
"foreign_keys": {"incoming": [], "outgoing": []}
|
||||||
}, {
|
}, {
|
||||||
'columns': ['id', 'content', 'content2'],
|
'columns': ['id', 'content', 'content2'],
|
||||||
'name': 'primary_key_multiple_columns',
|
'name': 'primary_key_multiple_columns',
|
||||||
|
|
@ -1281,3 +1290,21 @@ def test_config_force_https_urls():
|
||||||
"toggle_url"
|
"toggle_url"
|
||||||
].startswith("https://")
|
].startswith("https://")
|
||||||
assert response.json["suggested_facets"][0]["toggle_url"].startswith("https://")
|
assert response.json["suggested_facets"][0]["toggle_url"].startswith("https://")
|
||||||
|
|
||||||
|
|
||||||
|
def test_infinity_returned_as_null(app_client):
|
||||||
|
response = app_client.get("/fixtures/infinity.json?_shape=array")
|
||||||
|
assert [
|
||||||
|
{"rowid": 1, "value": None},
|
||||||
|
{"rowid": 2, "value": None},
|
||||||
|
{"rowid": 3, "value": 1.5}
|
||||||
|
] == response.json
|
||||||
|
|
||||||
|
|
||||||
|
def test_infinity_returned_as_invalid_json_if_requested(app_client):
|
||||||
|
response = app_client.get("/fixtures/infinity.json?_shape=array&_json_infinity=1")
|
||||||
|
assert [
|
||||||
|
{"rowid": 1, "value": float("inf")},
|
||||||
|
{"rowid": 2, "value": float("-inf")},
|
||||||
|
{"rowid": 3, "value": 1.5}
|
||||||
|
] == response.json
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue