diff --git a/datasette/views/table.py b/datasette/views/table.py index 79af60c0..7f130159 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -121,7 +121,9 @@ class RowTableShared(BaseView): if plugin_display_value is not None: display_value = plugin_display_value elif isinstance(value, bytes): - display_value = jinja2.Markup("<{} bytes>".format(len(value))) + display_value = jinja2.Markup("<Binary data: {} byte{}>".format( + len(value), "" if len(value) == 1 else "s") + ) elif isinstance(value, dict): # It's an expanded foreign key - display link to other row label = value["label"] diff --git a/tests/fixtures.py b/tests/fixtures.py index cb6f7a39..62758cb9 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -36,6 +36,9 @@ def make_app_client( filepath = os.path.join(tmpdir, filename) conn = sqlite3.connect(filepath) conn.executescript(TABLES) + for sql, params in TABLE_PARAMETERIZED_SQL: + with conn: + conn.execute(sql, params) os.chdir(os.path.dirname(filepath)) plugins_dir = os.path.join(tmpdir, "plugins") os.mkdir(plugins_dir) @@ -550,6 +553,10 @@ VALUES (2, 0, 'MC', 4, 'Arcadia Planitia', '[]') ; +CREATE TABLE binary_data ( + data BLOB +); + INSERT INTO simple_primary_key VALUES (1, 'hello'); INSERT INTO simple_primary_key VALUES (2, 'world'); INSERT INTO simple_primary_key VALUES (3, ''); @@ -589,6 +596,9 @@ CREATE VIEW searchable_view_configured_by_metadata AS **row ).replace('None', 'null') for row in generate_sortable_rows(201) ]) +TABLE_PARAMETERIZED_SQL = [( + "insert into binary_data (data) values (?);", [b'this is binary data'] +)] if __name__ == '__main__': # Can be called with data.db OR data.db metadata.json @@ -600,6 +610,9 @@ if __name__ == '__main__': if db_filename.endswith(".db"): conn = sqlite3.connect(db_filename) conn.executescript(TABLES) + for sql, params in TABLE_PARAMETERIZED_SQL: + with conn: + conn.execute(sql, params) print("Test tables written to {}".format(db_filename)) if metadata_filename: open(metadata_filename, 'w').write(json.dumps(METADATA)) diff --git a/tests/test_api.py b/tests/test_api.py index c1687c01..e981e346 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -23,7 +23,7 @@ def test_homepage(app_client): assert response.json.keys() == {"fixtures": 0}.keys() d = response.json["fixtures"] assert d["name"] == "fixtures" - assert d["tables_count"] == 25 + assert d["tables_count"] == 26 assert len(d["tables_truncated"]) == 5 assert d["tables_more"] is True # 4 hidden FTS tables + no_primary_key (hidden in metadata) @@ -53,6 +53,14 @@ def test_database_page(app_client): 'foreign_keys': {'incoming': [], 'outgoing': []}, 'fts_table': None, 'primary_keys': ['pk'], + }, { + 'columns': ['data'], + 'count': 1, + 'foreign_keys': {'incoming': [], 'outgoing': []}, + 'fts_table': None, + 'hidden': False, + 'name': 'binary_data', + 'primary_keys': [] }, { 'columns': ['pk', 'f1', 'f2', 'f3'], 'name': 'complex_foreign_keys', diff --git a/tests/test_html.py b/tests/test_html.py index a32734f3..402246c7 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -883,3 +883,19 @@ def test_extra_where_clauses(app_client): "/fixtures/facetable?_where=city_id%3D1", "/fixtures/facetable?_where=neighborhood%3D%27Dogpatch%27" ] == hrefs + + +def test_binary_data_display(app_client): + response = app_client.get("/fixtures/binary_data") + assert response.status == 200 + table = Soup(response.body, "html.parser").find("table") + expected_tds = [ + [ + '